这篇文章将为大家详细讲解有关MyBatis的知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。而在 MyBatis 3 中,提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。
提示: Java 注解的表达能力和灵活性十分有限。尽管MyBatis团队花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建。
经验对于单表的操作使用注解更加便利,但是对于复杂的多表,使用注解模式就显得难以维护建议使用XML。
常用注解
注解 | 用途 |
---|---|
@Insert | 新增 |
@Update | 更新 |
@Delete | 删除 |
@Select | 查询 |
@Result | 封装结果集 |
@Results | 与@Result配合,封装多个结果集 |
@One | 实现一对一结果集封装 |
@Many | 实现一对多结果集封装 |
以下的查询案例和要求均和XML模式一致,只是将xml操作替换为注解操作
对于注解的查询操作是不需要Mapper.xml配置文件的,因为sql的配置和结果映射都通过注解实现了
SqlMapConfig.xml更新
<mappers>
<!-- 注解方式Mapper的信息已经在接口中使用功能注解实现,所以扫描接口解析注解获取 -->
<package name="com.zyj.mapper"/>
</mappers>
对于基础的单表新增、更新、查询、删除操作如下,sql语句和xml一致,这里不多介绍。
public interface UserMapper {
// 新增
@Insert(value = "insert into user(id, username, `password`, birthday) values (#{id}, #{username}, #{password}, #{birthday})")
void addUser(User user);
// 更新
@Update(value = "update user set username = #{username}, `password` = #{password}, birthday = #{birthday} where id = #{id}")
void updateUser(User user);
// 查询
@Select(value = "select * from user")
List<User> selectAll();
// 删除
@Delete(value = "delete from user where id = #{id}")
void deleteUser(Integer id);
}
执行过程:
1)执行@Select
标签的sql语句。
2)执行@Results
标签的语句封装@Select
的查询结果。
3)封装结果的时候有一个属性是user
,内部的one属性关联到了另外一个查询结果。所以就会去UserMapper
中执行selectById
根据 column=uid
将 order
的uid
作为参数去查询结果。
// 订单一对一查询
public interface OrdersMapper {
// select * from orders o left join user u on o.uid = u.id
@Results({
@Result(property = "id", column = "id"),
@Result(property = "ordertime", column = "ordertime"),
@Result(property = "total", column = "total"),
@Result(
javaType = User.class,
property = "user",
column = "uid",
one = @One(select = "com.zyj.mapper.UserMapper.selectById"))
})
@Select(value = "select * from orders")
List<Order> findAllOrderAndUser();
}
// 用户查询
public interface UserMapper {
@Select(value = "select * from user where id = #{id}")
User selectById(Integer id);
}
注解和标签对应关系总结:
注解 | 标签 |
---|---|
@Select | select |
@Results | resultMap |
@Result | id和<result |
@One | association |
执行过程:
1)执行@Select
标签的sql语句。
2)执行@Results
标签的语句封装@Select
的查询结果。
3)封装结果的时候有一个属性是orderList
,内部的Many属性关联到了另外一个查询结果。所以就会去OrderMapper
中执行selectByUId
根据 column=id
将 User
的id
作为参数去查询结果。
// 用户查询一对多
public interface UserMapper {
// select * from user u left join orders o on u.id = o.uid;
@Results({
@Result(property = "id", column = "id"),
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "birthday", column = "birthday"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.zyj.mapper.OrdersMapper.selectByUId")
)
})
@Select(value = "select * from user")
List<User> findAllUserAndOrder();
}
// 根据用户id查询用户订单
public interface OrdersMapper {
// 根据用户id返回查询结果
@Select(value = "select * from orders where uid = #{uid}")
List<Order> selectByUId(Integer uid);
}
注解和标签对应关系总结:
注解 | 标签 |
---|---|
@Select | <select> |
@Results | <resultMap> |
@Result | <id>和<result> |
@Many | <collection> |
执行过程:
1)执行@Select
标签的sql语句。
2)执行@Results
标签的语句封装@Select
的查询结果。
3)封装结果的时候有一个属性是roleList
,内部的Many属性关联到了另外一个查询结果。所以就会去RoleMapper
中执行selectByUserId
根据 column=id
将 User
的id
作为参数去查询结果。
public interface UserMapper {
// select * from user u left join sys_user_role ur on u.id = ur.userid left join sys_role r on ur.roleid = r.id;
@Results({
@Result(property = "id", column = "id"),
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "birthday", column = "birthday"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.zyj.mapper.RoleMapper.selectByUserId")
)
})
@Select(value = "select * from user")
List<User> findAllUserAndRole();
}
// 根据用户id查询角色
public interface RoleMapper {
@Select(value = "select r.* from sys_role r inner join sys_user_role ur on r.id = ur.roleid where userid = #{uid}")
List<Role> selectByUserId(Integer uid);
}
注解和标签对应关系总结:
注解 | 标签 |
---|---|
@Select | select |
@Results | resultMap |
@Result | id和result |
@Many | collection |
MyBatis提供的动态Sql标签在注解模式中也是一样适用,但是写法和刚才的一对一、一对多、多对多 的查询有所差异。作用和效果是一样的。所以这里只给出一个案例即可。
@Update({"<script>",
"update Author",
" <set>",
" <if test='username != null'>username=#{username},</if>",
" <if test='password != null'>password=#{password},</if>",
" <if test='email != null'>email=#{email},</if>",
" <if test='bio != null'>bio=#{bio}</if>",
" </set>",
"where id=#{id}",
"</script>"})
void updateAuthorValues(Author author);
如果想在注解的映射器接口中使用动态SQL,那么可以使用script元素。
Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。 两个缓存的关系如下图:
每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。
1)在同一个sqlSession中,对User用户表根据id进行2次查询,观察控制台的sql打印情况。
@Test
public void test1(){
// 获取一个sqlSession
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用sqlSession执行第一次查询
User u1 = userMapper.selectUserByUserId(1);
System.out.println(u1);
// 使用sqlSession执行第二次查询
User u2 = userMapper.selectUserByUserId(1);
System.out.println(u2);
sqlSession.close();
}
2)在同一个sqlSession中,对User用户表根据id进行2次查询。但是,中间对查询到的用户执行Update更新操作,并提交事务,观察控制台的sql打印情况。
@Test
public void test2(){
// 获取一个sqlSession
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用sqlSession执行第一次查询
User u1 = userMapper.selectUserByUserId( 1 );
System.out.println(u1);
// 第二次查询之前执行更新操作并提交事务
u1.setSex("女");
userMapper.updateUserByUserId(u1);
sqlSession.commit();
// 使用sqlSession执行第二次查询
User u2 = userMapper.selectUserByUserId(1);
System.out.println(u2);
sqlSession.close();
}
总结:
1)第一次查询用户的时候,会在一级缓存中去查询用户信息,如果查询不到就去数据库中查询。并将查询到的结果更新到以及缓存中。
2)如果同一个SqlSession中执行了commit事务提交操作(增加、更新、删除),那么就会清空SqlSession中的缓存信息,避免下次查询的时候出现脏数据。
3)第二次查询的时候同样去一级缓存查询,如果有值就获取返回,如果没有就查询数据库并添加到一级缓存中。
二级缓存和一级缓存原理类似,只不过缓存的级别更高而已。一级缓存针对sqlSession,但是二级缓存就针对Mapper文件。所以二级缓存可以被多个sqlSession共享。
二级缓存和一级缓存不一样,一级缓存默认都是开启的,二级缓存默认是关闭的。所以需要配置开启。二级缓存的开启需要配置2个地方。
总开关开启二级缓存SqlMapConfig.xml配置文件开启。
<!-- 二级缓存总开关 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
由于二级缓存是Mapper级别的缓存,所以可以针对单个Mapper配置是否需要开启。
<!--对应的Mapper.xml开启二级缓存。如:UserMapper.xml、OrderMapper.xml-->
<cache></cache>
基于上诉流程测试二级缓存
@Test
public` `void` `testTwoCache(){
// 获取sqlSession
SqlSession sqlSession1 = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
String statement = "com.zyj.UserMapper.selectById" ;
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper. class );
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper. class );
UserMapper userMapper3 = sqlSession2.getMapper(UserMapper. class );
// 第一次执行查询,结果会放入二级缓存中
User u1 = userMapper1.selectById( 1 );
System.out.println(u1);
sqlSession1.close(); // 关闭第一个session
// 执行更新操作,并提交
u1.setUsername("知春秋");
userMapper3.selectById(u1);
sqlSession3.commit();
// 第二次查询,由于更新操作导致二级缓存被更新,所以会重新查询数据库
User u2 = userMapper2.selectById( 1 );
System.out.println(u2);
sqlSession2.close();
}
关于“MyBatis的知识点有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/zhangyongjun/blog/4644244