mybatis的xml的映射器-02

mybatis的xml映射器

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

xml的基本映射标签

1.select标签

mapper 接口中的方法:
/**
 * 查询所有
 */
List selectList();

mapper xml的映射

测试代码:

 @Test
 public void testSelectList(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 调用查询方法
    mapper.selectList();

    //关闭资源
    SqlSessionUtils.close(sqlSession);

}

2.insert 标签

mapper 接口中的方法:
/**
 * 查询所有
 */
List selectList();

mapper xml的映射

测试代码:

    @Test
    public void testInsert(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值

        User u = new User();
        u.setName("王语嫣");
        u.setPhone("1234");
        u.setPwd("abc");
        System.out.println(u);
        int i = mapper.insertUser(u);
        System.out.println(u);

        //提交事务
        sqlSession.commit();

        //关闭资源
        SqlSessionUtils.close(sqlSession);

    }

插入日志查看:
User{id=null, name='王语嫣', pwd='abc', phone='1234'}
DEBUG [main] - ==>  Preparing: insert into t_user(name ,pwd,phone) values(?,?,?) 
DEBUG [main] - ==> Parameters: 王语嫣(String), abc(String), 1234(String)
DEBUG [main] - <==    Updates: 1
User{id=6, name='王语嫣', pwd='abc', phone='1234'}

keyProperty="id" keyColumn="id" useGeneratedKeys="true" 配置了可以把 插入的数据的自增id
返回给对象

3.update 标签

mapper 接口中的方法:
  /**
  * 修改user
  */
 int updateUser(User u);

mapper xml的映射

    update  t_user set
        name = #{name},
        pwd = #{pwd},
        phone = #{phone}
    where id = #{id}

测试代码:

@Test
public void testUpdate(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值

    User u = new User();
    u.setId(3);
    u.setName("周芷若");
    u.setPhone("1234");
    u.setPwd("abc");
    System.out.println(u);
    int i = mapper.updateUser(u);
    System.out.println(u);

    //提交事务
    sqlSession.commit();

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}

4.delete标签

mapper 接口中的方法:
/**
 * 通过id删除
 */
int deleteUser(Integer id);

mapper xml的映射

    delete from t_user where id = #{id}

测试代码:

    @Test
    public void testDelete(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值
        int i = mapper.deleteUser(2);
        System.out.println(i);

        //提交事务
        sqlSession.commit();

        //关闭资源
        SqlSessionUtils.close(sqlSession);
    }

5.注意事项

  1. 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中

  2. mybatis的默认手动提交事务,进行更新操作(insert,update,delete) 操作后 一定要提交事务 commit()

6.参数

  1. 之前见到的所有语句都使用了简单的参数形式。但实际上,参数是 MyBatis 非常强大的元素。对于大多数简单的使用场景,你都不需要使用复杂的参数,比如:

  2. 一个参数

    
    

    上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名。原始类型或简单数据类型(比如 IntegerString)因为没有其它属性,会用它们的值来作为参数。

    
      insert into t_user (name, pwd,phone)
      values (#{name}, #{pwd}, #{phone})
    
    

    如果 User 类型的参数对象传递到了语句中,会查找 id、username 和 password 属性,然后将它们的值传入预处理语句的参数中。

    对传递语句参数来说,这种方式真是干脆利落。不过参数映射的功能远不止于此。

    和 MyBatis 的其它部分一样,参数也可以指定一个特殊的数据类型。

    #{id,javaType=int,jdbcType=NUMERIC}
    
    对于数值类型,还可以设置 numericScale 指定小数点后保留的位数。
    #{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
    

    尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就行了。

    #{name,jdbcType=VARCHAR}
    

7.字符串替换

默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。

#{} 参数占位符


测试日志:

DEBUG [main] - ==>  Preparing: select * from t_user where name = ?    //sql的占位符 
DEBUG [main] - ==> Parameters: 张三(String)
TRACE [main] - <==    Columns: id, name, pwd, phone
TRACE [main] - <==        Row: 1, 张三, 123456, 123456
DEBUG [main] - <==      Total: 1
User{id=1, name='张三', pwd='123456', phone='123456'}

${} 参数拼接


测试代码:

public void testSelectName(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值    参数设置注意加:''
    User user = mapper.selectByName("'张三'");

    System.out.println(user);

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}

测试日志:

DEBUG [main] - ==>  Preparing: select * from t_user where name = '张三' 
// sql的字符串拼接
DEBUG [main] - ==> Parameters: 
TRACE [main] - <==    Columns: id, name, pwd, phone
TRACE [main] - <==        Row: 1, 张三, 123456, 123456
DEBUG [main] - <==      Total: 1
User{id=1, name='张三', pwd='123456', phone='123456'}

提示 ${} 用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击

8. 结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

之前你已经见过简单映射语句的示例,它们没有显式指定 resultMap

在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上会发生什么?

javaBean:

public class User {

    private Integer id;

    private String name;

    private String pwd;

    private String phone;
}

xml的映射:


类名和属性名不能匹配

测试结果:

@Test
public void testSelectOne(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值
    User user = mapper.selectByPrimaryKey(4);

    System.out.println(user);

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}

查看日志:

DEBUG [main] - ==>  Preparing: select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = ? 
DEBUG [main] - ==> Parameters: 4(Integer)
TRACE [main] - <==    Columns: u_id, u_name, u_password, u_phone
TRACE [main] - <==        Row: 4, 郭靖, aaa, 1234
DEBUG [main] - <==      Total: 1
null

Columns 和 resultType 不匹配 

使用resultMap是解决列名不匹配的一种方式



    
    
    
    




测试代码:

    @Test
    public void testSelectOne(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值
        User user = mapper.selectByPrimaryKey(4);

        System.out.println(user);

        //关闭资源
        SqlSessionUtils.close(sqlSession);
    }

测试日志:

DEBUG [main] - ==>  Preparing: select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = ? 
DEBUG [main] - ==> Parameters: 4(Integer)
TRACE [main] - <==    Columns: u_id, u_name, u_password, u_phone
TRACE [main] - <==        Row: 4, 郭靖, aaa, 1234
DEBUG [main] - <==      Total: 1
User{id=4, name='郭靖', pwd='aaa', phone='1234'}

9 mybatis的注解开发:

映射器注解

设计初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。而在 MyBatis 3 中,我们提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。

提示 不幸的是,Java 注解的表达能力和灵活性十分有限。尽管我们花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建——我们真没开玩笑。

常用的注解如下:

@Select 	查询数据注解
@Insert 	插入数据注解
@Delete 	删除数据注解
@Update 	修改数据注解
@Options 	选项配置
@Results 	手动映射配置

@Result:	@results中的具体的某一列的映射信息配置 
在列和属性或字段之间的单个结果映射。属性:id、column、javaType、jdbcType、typeHandler、one、many。id 属性和 XML 元素  相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。one 属性是一个关联,和  类似,而 many 属性则是集合关联,和  类似。这样命名是为了避免产生名称冲突。

注解的案例:

public interface UserMapperAnnotation {

 @Select(" select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = #{id}")
    @Results({
            @Result(id = true,property = "id",column = "u_id"),
            @Result(property = "name",column = "u_name"),
            @Result(property = "pwd",column = "u_password"),
            @Result(property = "phone",column = "u_phone"),
    })
    User selectByPrimaryKey(Integer id);

    @Select("select * from t_user")
    List selectList();

    @Insert("insert into t_user(name,pwd,phone) values(#{name},#{pwd},#{phone})")
    @Options(
            keyProperty ="id",
            keyColumn = "id",
            useGeneratedKeys = true
    )
    int insertUser(User u);

    @Delete("delete from t_user where id = #{id}")
    int deleteUserById(Integer id);

    @Update("update t_user set name = #{name},pwd=#{pwd},phone = #{phone} where id = #{id}")
    int updateUser(User u);

}

注意: 需要在config中配置mapper接口:


            
        
    

测试代码:

package cn.hk.test;

import cn.hk.bean.User;
import cn.hk.mapper.UserMapperAnnotation;
import cn.hk.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

/**
 * @author 黄药师
 * @date 2020-05-11 16:16
 * @desc
 */
public class UserAnnotationTest {

    @Test
    public void testSelectOne(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);

        User user = mapper.selectByPrimaryKey(1);

        System.out.println(user);

        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testSelectList(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);

        List users = mapper.selectList();

        System.out.println(users);

        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testInsert(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);


        User user = new User();

        user.setPhone("1111");
        user.setPwd("1234");
        user.setName("黄蓉");

        System.out.println(user);
        int i = mapper.insertUser(user);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        System.out.println(user);

        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }


    @Test
    public void testDelete(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);

        int i = mapper.deleteUserById(3);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testUpdate(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);

        User user = new User();

        user.setPhone("1111");
        user.setPwd("1234");
        user.setName("周伯通");
        user.setId(1);

        int i = mapper.updateUser(user);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }
}

10 多参数的处理

传递多个参数给一个映射器方法。在多个参数的情况下,默认它们将会以 param 加上它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果你想(在有多个参数时)自定义参数的名称,那么你可以在参数上使用 @Param(“paramName”) 注解。

如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。否则在默认情况下,除 RowBounds 以外的参数会以 “param” 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param("person"),参数就会被命名为 #{person}

  1. 多个参数的使用

    不使用注解的多参数xml映射:
        /**
         *  查询 多个参数
         * @return
         */
     User selectUser(String name,String pwd);
       
       
     
     
    
    使用注解的多参数设置:
    User selectUser01(@Param("username") String name,@Param("password") String pwd);  
    
    
    
  2. 把多个参数封装成一个map

    User selectUser02(Map map);
    
    
    
    

    测试代码:

        @Test
        public void testSelectUser02(){
    
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            HashMap map = new HashMap<>();
    
            map.put("name","王语嫣");
            map.put("pwd","abc");
    
            User user = mapper.selectUser02(map);
            System.out.println(user);
    
        }
    
  3. 把多个参数封装成对象

    User selectUser03(User user);
    
    
    
    
    

    测试代码:

        @Test
        public void testSelectUser03(){
    
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            User user = new User();
    
            user.setName("王语嫣");
            user.setPwd("abc");
    
            User u = mapper.selectUser03(user);
            System.out.println(u);
    
            SqlSessionUtils.close(sqlSession);
    
        }
    

你可能感兴趣的:(框架)