目录
1.在核心配置文件SqlMapConfig.xml中注册接口
3.在持久层接口上方加注解@CacheNamespace(blocking = true)为接口中所有方法开启二级缓存
(2)在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)
1.在持久层接口中创建分解后的查询方法(包括主表的查询配置自定义映射关系)
2.在方法中构建动态Sql
四、MyBatis注解开发_自定义映射关系
五、MyBatis注解开发_开启二级缓存
六、MyBatis注解开发_关联查询
七、注解和映射文件对比
一、MyBatis注解开发介绍:
MyBatis可以使用注解替代映射文件。映射文件的作用就是定义Sql 语句,可以在持久层接口上使用 @Select/@Delete/@Insert/@Update定义Sql语句,这样就不需要使用映射文件了,注解开发底层还是会转换为xml映射文件的方式。
二、MyBatis注解开发_增删改查
1.在核心配置文件SqlMapConfig.xml中注册接口
<mappers> <package name="com.itbaizhan.mapper"/> mappers>2.写一套增删改查
(1)查询user表所有数据
持久层接口方法
// 查询user表所有数据 @Select("select * from user") ListfindAll(); 测试方法
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(){ Listall = 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}") ListfindByUsername(String username); 测试方法
@Test public void testFindByUsername(){ Listall = userMapper.findByUsername("上海"); all.forEach(System.out::println); }
三、MyBatis注解开发_动态Sql
MyBatis注解开发中有两种方式构建动态Sql,1.使用脚本标签")
测试方法
- @Test
- public void testFindByCondition(){
- User user = new User();
- user.setUsername("%shanghai%");
- List
all = userMapper.findByCondition(user); - all.forEach(System.out::println);
- }
类方法
- 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") ListfindAll(); // 通过id查询user表中数据,使用resultMap注解来引用上述自定义的映射关系 @ResultMap("userMapper") @Select("select * from user where id = #{id}") User findById(int userId); }测试方法
@Test public void testFindAll(){ Listall = 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是默认开启缓存的,所以这里可以不用配置
<settings> <setting name="cacheEnabled" value="true"/> settings>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 Liststudents; // 省略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)) }) ListfindAll(); }
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); Listall = 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)) }) ListfindAllClasses(); }
public interface StudentMapper { // 一对多关联查询,查询所有班级并关联查询出班级对应的学生(从表:Student) @Select("select * from student where classId = #{classId}") ListfindByClassId(int classId); }2.测试方法
// 一对多关联查询 @Test public void testFindAllClasses(){ ClassesMapper classesMapper = session.getMapper(ClassesMapper.class); Listall = classesMapper.findAllClasses(); all.forEach(System.out::println); }
七、注解和映射文件对比
MyBatis中更推荐使用映射文件开发,Spring、SpringBoot更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:
1.映射文件开发优点:
(1)代码与 Sql 语句是解耦的,修改时只需修改配置文件,无需修改源码。(2)Sql 语句集中,利于快速了解和维护项目。(3)级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。
2.注解开发优点:
配置简单,开发效率高。类型安全,在编译期即可进行校验,不用等到运行时才发现错误。因为在编译期IDEA会发现编译错误并报错,xml文件不会报错。