08 MyBatis 注解开发

目录

一、MyBatis注解开发介绍:

二、MyBatis注解开发_增删改查

1.在核心配置文件SqlMapConfig.xml中注册接口

2.写一套增删改查

(1)查询user表所有数据

(2)向user表添加数据

(3)根据id更新user表

(4)根据id删除user表

(5)模糊查询

三、MyBatis注解开发_动态Sql

1.使用脚本标签

2.在方法中构建动态Sql

四、MyBatis注解开发_自定义映射关系

1.介绍

2.用法如下:

五、MyBatis注解开发_开启二级缓存

1.pojo类实现Serializable接口

2.在MyBatis配置文件中添加如下设置:

3.在持久层接口上方加注解@CacheNamespace(blocking = true)为接口中所有方法开启二级缓存

4.测试方法

5.测试结果

6.结论:

六、MyBatis注解开发_关联查询

1.一对一关联查询

(1)创建实体类

(2)在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)

(3)测试方法

2.一对多关联查询

1.在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)

2.测试方法

七、注解和映射文件对比

1.映射文件开发优点:

2.注解开发优点:


2.在方法中构建动态Sql

四、MyBatis注解开发_自定义映射关系

五、MyBatis注解开发_开启二级缓存

六、MyBatis注解开发_关联查询

七、注解和映射文件对比

一、MyBatis注解开发介绍:

08 MyBatis 注解开发_第1张图片

 MyBatis可以使用注解替代映射文件。映射文件的作用就是定义Sql 语句,可以在持久层接口上使用 @Select/@Delete/@Insert/@Update定义Sql语句,这样就不需要使用映射文件了,注解开发底层还是会转换为xml映射文件的方式

二、MyBatis注解开发_增删改查

1.在核心配置文件SqlMapConfig.xml中注册接口

   
    
        


        

        
    

2.写一套增删改查

(1)查询user表所有数据

持久层接口方法

//    查询user表所有数据
    @Select("select * from user")
    List findAll();

测试方法

public class TestUserMapper {
    InputStream is = null;
    SqlSession session = null;
    UserMapper userMapper = null;

    @Before
    public void testBefore() throws IOException {
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        session = factory.openSession();
        userMapper = session.getMapper(UserMapper.class);
    }

    @After
    public void testAfter() throws IOException {
        session.close();
        is.close();
    }

    @Test
    public void testFindAll(){
        List all = userMapper.findAll();
        all.forEach(System.out::println);
    }
}

(2)向user表添加数据

持久层接口方法

//    主键回填
    @SelectKey(keyColumn = "id",keyProperty = "id", resultType = int.class,
                before = false, statement = "SELECT LAST_INSERT_ID()")
//    向user表添加数据
    @Insert("insert into user(username,sex,address) values(#{username},#{sex},#{address})")
    void add(User user);

测试方法

 @Test
    public void testAdd(){
        User user = new User("北京程序员","女","上海");
        System.out.println(user);
        userMapper.add(user);
        session.commit();
        System.out.println(user);
    }

(3)根据id更新user表

持久层接口方法

//    根据id更新user表
    @Update("update user set username = #{username},sex = #{sex},address = #{address} where id = #{id}")
    void update(User user);

测试方法

   @Test
    public void testUpdate(){
        User user = new User(4,"上海","男","北京");
        userMapper.update(user);
        session.commit();
    }

(4)根据id删除user表

持久层接口方法

//    根据id删除user表
    @Delete("delete from user where id = #{id}")
    void delete(int userId);

测试方法

 @Test
    public void testDelete(){
        userMapper.delete(21);
        session.commit();
    }

(5)模糊查询

持久层接口方法

//    模糊查询
    @Select("select * from user where username like '%${value}%'")
//    @Select("select * from user where username like #{username}")
    List findByUsername(String username);

测试方法

   @Test
    public void testFindByUsername(){
        List all = userMapper.findByUsername("上海");
        all.forEach(System.out::println);
    }

三、MyBatis注解开发_动态Sql

08 MyBatis 注解开发_第2张图片

 MyBatis注解开发中有两种方式构建动态Sql,1.使用脚本标签") List findByCondition(User user);

测试方法

    @Test
    public void testFindByCondition(){
        User user = new User();
        user.setUsername("%shanghai%");
        List all = userMapper.findByCondition(user);
        all.forEach(System.out::println);
    }

2.在方法中构建动态Sql

MyBatis 中有 @SelectProvider @UpdateProvider @DeleteProvider @InsertProvider 注 解。当使用这些注解时将不在注解中直接编写 SQL, 而是调用某个类的方法来生成SQL

类方法

public class UserProvider {
    public String findByConditionSql(User user){
        StringBuffer sb = new StringBuffer("select * from user where 1=1 ");
                if(user.getUsername() != null && user.getUsername().length() != 0){
                    sb.append("and username like #{username}");
                }
                if(user.getSex() != null && user.getSex().length() != 0){
                    sb.append("and sex = #{sex}");
                }
                if(user.getAddress() != null && user.getAddress().length() != 0){
                    sb.append("and address = #{address}");
                }
         return  sb.toString();
    }
}

持久层接口方法

//    用动态SQL语句进行任意条件查询2
    @SelectProvider(type = UserProvider.class,method = "findByConditionSql")
    List findByCondition(User user);

测试方法

    @Test
    public void testFindByCondition(){
        User user = new User();
        user.setUsername("%shanghai%");
        List all = userMapper.findByCondition(user);
        all.forEach(System.out::println);
    }

四、MyBatis注解开发_自定义映射关系

public class User implements Serializable {
    private int id;
    private String username;
    private String sex;
    private String address;

//省略构造器、getter、setter、toString方法
}
08 MyBatis 注解开发_第3张图片

1.介绍

 如上述代码图片所示,当POJO属性名与数据库列名不一致时,需要自定义实体类和结果集的映射关系,在MyBatis注解开发中,使用 @Results 定义并使用自定义映射,使用 @ResultMap 使用自定义映射。

2.用法如下:

持久层接口方法

public interface UserMapper {
//注解开发底层还是会转换为xml映射文件的方式

//    自定义映射关系
    @Results(id = "userMapper", value = {
            @Result(id = true,property = "id", column = "id"),
            @Result(property = "username", column = "username1"),
            @Result(property = "sex", column = "sex1"),
            @Result(property = "address", column = "address1")
    })
//    查询user表所有数据
    @Select("select * from user")
    List findAll();


//    通过id查询user表中数据,使用resultMap注解来引用上述自定义的映射关系
    @ResultMap("userMapper")
    @Select("select * from user where id = #{id}")
    User findById(int userId);
}

测试方法

    @Test
    public void testFindAll(){
        List all = userMapper.findAll();
        all.forEach(System.out::println);
    }

    @Test
    public void testFindById(){
        User user = userMapper.findById(3);
        System.out.println(user);
    }

五、MyBatis注解开发_开启二级缓存

08 MyBatis 注解开发_第4张图片

MyBatis 默认开启一级缓存,接下来我们来看在注解开发时如何使用二级缓存:

1.pojo类实现Serializable接口

public class User implements Serializable {
    private int id;
    private String username;
    private String sex;
    private String address;

//省略构造器、getter、setter、toString方法
}

2.在MyBatis配置文件中添加如下设置:

因为MyBatis是默认开启缓存的,所以这里可以不用配置


     

3.在持久层接口上方加注解@CacheNamespace(blocking = true)为接口中所有方法开启二级缓存

@CacheNamespace(blocking = true)
public interface UserMapper {
   //省略接口方法
}

4.测试方法

public class TestUserMapper2 {
    @Test
    public void testCache() throws IOException {
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session1 = factory.openSession();
        SqlSession session2 = factory.openSession();

        User user1 = session1.getMapper(UserMapper.class).findById(1);
        System.out.println(user1);
        System.out.println(user1.hashCode());
        session1.commit(); // 清空一次缓存,将数据存到二级缓存
        User user2 = session2.getMapper(UserMapper.class).findById(1);
        System.out.println(user2);
        System.out.println(user2.hashCode());
    }
}

5.测试结果

08 MyBatis 注解开发_第5张图片

6.结论:

只执行了一次sql语句,第二次得到的数据是二级缓存中的,两个user对象的HashCode值不同是因为:一级缓存存的是对象,二级缓存存的是数据,从二级缓存中拿到数据后,会将数据再次封装为对象,所以两次HashCode值不同。

六、MyBatis注解开发_关联查询

08 MyBatis 注解开发_第6张图片

 在MyBatis的注解开发中对于多表查询只支持分解查询,不支持连接查询。

1.一对一关联查询

(1)创建实体类

public class Student {
    private int sid;
    private String name;
    private int age;
    private String sex;
    private Classes classes;
    // 省略getter/setter/toString
}
public class Classes {
    private int cid;
    private String className;
    private List students;
    // 省略getter/setter/toString
}

(2)在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)

public interface StudentMapper {

//    一对一关联查询,查询学生并关联查询出班级(主表:Student)
    @Select("select * from student")
//    自定义映射关系
    @Results(id = "studentMapper", value = {
            @Result(id = true,property = "sid", column = "sid"),
            @Result(property = "name", column = "name"),
            @Result(property = "age", column = "age"),
            @Result(property = "sex", column = "sex"),
            /**
             * property:属性名
             * column:关联列主键名
             * one:表示该属性是一个对象,即一对一关联查询
             * select:调用从表中的方法
             * fetchType:加载方式
             * eager:立即加载        lazy:懒加载(延迟加载)
             */
            @Result(property = "classes",column = "classId",
            one = @One(select = "com.itbaizhan.mapper.ClassesMapper.findByCid",
            fetchType = FetchType.EAGER))
    })
    List findAll();
}
public interface ClassesMapper {
//    一对一关联查询,查询学生并关联查询出班级(从表:Classes)
    @Select("select * from classes where cid = #{cid}")
    Classes findByCid(int cid);
}

(3)测试方法

  @Test
    public void testFindAll(){
        StudentMapper studentMapper = session.getMapper(StudentMapper.class);
        List all = studentMapper.findAll();
        all.forEach(System.out::println);
    }

2.一对多关联查询

1.在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)

public interface ClassesMapper {

//    一对多关联查询,查询所有班级并关联查询出班级对应的学生(主表:Classes)
    @Select("select * from classes")
    @Results(id = "classesMapper", value = {
            @Result(id = true,property = "cid",column = "cid"),
            @Result(property = "className",column = "className"),
            //many:表示一对多查询,该属性是一个集合
            @Result(property = "studentList",column = "cid",
            many = @Many(select = "com.itbaizhan.mapper.StudentMapper.findByClassId",
                    fetchType = FetchType.LAZY))
    })
    List findAllClasses();
}
public interface StudentMapper {

//    一对多关联查询,查询所有班级并关联查询出班级对应的学生(从表:Student)
    @Select("select * from student where classId = #{classId}")
    List findByClassId(int classId);
}

2.测试方法

//    一对多关联查询
    @Test
    public void testFindAllClasses(){
        ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
        List all = classesMapper.findAllClasses();
        all.forEach(System.out::println);
    }

七、注解和映射文件对比

08 MyBatis 注解开发_第7张图片

 MyBatis中更推荐使用映射文件开发,SpringSpringBoot更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:

1.映射文件开发优点:

(1)代码与 Sql 语句是解耦的,修改时只需修改配置文件,无需修改源码。
(2)Sql 语句集中,利于快速了解和维护项目。
(3)级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。

2.注解开发优点:

配置简单,开发效率高。
类型安全,在编译期即可进行校验,不用等到运行时才发现错误。因为在编译期IDEA会发现编译错误并报错,xml文件不会报错。

你可能感兴趣的:(MyBatis,mybatis)