目录
一、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注解开发介绍:
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
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方法 }
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注解开发_开启二级缓存
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.测试结果
6.结论:
只执行了一次sql语句,第二次得到的数据是二级缓存中的,两个user对象的HashCode值不同是因为:一级缓存存的是对象,二级缓存存的是数据,从二级缓存中拿到数据后,会将数据再次封装为对象,所以两次HashCode值不同。
六、MyBatis注解开发_关联查询
在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); }
七、注解和映射文件对比
MyBatis中更推荐使用映射文件开发,Spring、SpringBoot更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:
1.映射文件开发优点:
(1)代码与 Sql 语句是解耦的,修改时只需修改配置文件,无需修改源码。(2)Sql 语句集中,利于快速了解和维护项目。(3)级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。
2.注解开发优点:
配置简单,开发效率高。类型安全,在编译期即可进行校验,不用等到运行时才发现错误。因为在编译期IDEA会发现编译错误并报错,xml文件不会报错。