Mybatis小结二:映射,存储过程,缓存
Posted 名人堂之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis小结二:映射,存储过程,缓存相关的知识,希望对你有一定的参考价值。
一、一对一:
这个地方与hibernate对比,hibernate 的关联操作应该就是id相等,但是mybatis可以用另外几种方法关联吧,left join or right join。 这些方法有时候可能会得到我们想要的结果,这是hibernate所做不到的吧。
<mapper namespace="ClassesMapper">
<!-- select * from class c RIGHT join teacher t on c.teacher_id = t.t_id where t.t_id=#{id} -->
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
</select>
<!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
<resultMap type="Classes" id="ClassResultMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
</mapper>
二、一对多:
是用到了collection,,相当于set集合的效果。这里需要稍微注意的是,association 和 collection 对应实体类Classes中的成员变量,一个是类Teacher,一个是集合students(
<select id="getClass3" parameterType="int" resultMap="ClassResultMap3">
select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="Classes" id="ClassResultMap3">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" column="teacher_id" javaType="Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<!-- ofType指定students集合中的对象类型 -->
<collection property="students" ofType="Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
三、调用存储过程:
需要注意的是in和out,这里传入的是一个map,最后的执行结果会返回到usercount里面,需要再取出来查看结果。
<select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
CALL test.ges_user_count(?,?)
</select>
<parameterMap type="java.util.Map" id="getUserCountMap">
<parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
<parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
测试代码
Map<String, Integer> parameterMap = new HashMap<String, Integer>();
parameterMap.put("sexid", 1);
parameterMap.put("usercount", -1);
cm.getUserCount(parameterMap);
System.out.println("-----------Midas-----------hm值=" + parameterMap + "," + "当前类=MybatisTest.testOne()");
报错无外乎以下几种问题
1.mysql里面压根没有那个存储过程
2.Mysql里存储过程的名字跟调用的存储过程名字不一样(名字写错了)
3.存储过程代码里面写了注释(中文、英文都删了吧)
4.接收的参数有问题
一级缓存,基于PerpetualCache 的hashmap本地缓存,存储作用域为Session,
session刷新或者关闭操作后,缓存清空
二级缓存,存储作用域为namespace,对应的那个mapper
四、一级缓存测试:
List<Classes> aClass = cm.getClass(3);
for(Classes classes : aClass){
System.out.println("-----------Midas-----------aclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
List<Classes> bClass = cm.getClass(3);
for(Classes classes : bClass){
System.out.println("-----------Midas-----------bclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
结果,可以从打印出的sql可以看出,sql语句只执行了一次。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 841283083.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3224f60b]
==> Preparing: select * from class c RIGHT join teacher t on c.teacher_id = t.t_id where t.t_id=?
==> Parameters: 3(Integer)
<== Columns: c_id, c_name, teacher_id, t_id, t_name
<== Row: null, null, null, 3, teacher3
<== Total: 1
-----------Midas-----------aclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
-----------Midas-----------bclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
执行不同的查询操作看一下。
List<Classes> aClass = cm.getClass(3);
for(Classes classes : aClass){
System.out.println("-----------Midas-----------aclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
List<Classes> bClass = cm.getClass(2);
for(Classes classes : bClass){
System.out.println("-----------Midas-----------bclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
结果,sql出现了两次。
==> Preparing: select * from class c RIGHT join teacher t on c.teacher_id = t.t_id where t.t_id=?
==> Parameters: 3(Integer)
<== Columns: c_id, c_name, teacher_id, t_id, t_name
<== Row: null, null, null, 3, teacher3
<== Total: 1
-----------Midas-----------aclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
==> Preparing: select * from class c RIGHT join teacher t on c.teacher_id = t.t_id where t.t_id=?
==> Parameters: 2(Integer)
<== Columns: c_id, c_name, teacher_id, t_id, t_name
<== Row: 2, class_b, 2, 2, teacher2
<== Total: 1
-----------Midas-----------bclasses值=Classes{id=2, name='class_b', teacher=Teacher [id=2, name=teacher2], students=null},当前类=MybatisTest.testOne()
五、二级缓存:
这里需要注意的是,必须要commit或者close之后,二级缓存才会有效果,毕竟需要刷新到mapper缓存中。对于CUD来说,事务提交后,缓存都会被清空。
而一级缓存,在commit后,查询相同的内容缓存就不会有作用了,这时候commit相当于清空一级缓存session。
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
SqlSession session3 = MybatisUtils.getSession();
ClassesMapper cm = session.getMapper(ClassesMapper.class);
ClassesMapper mapper = session2.getMapper(ClassesMapper.class);
ClassesMapper mapper3 = session3.getMapper(ClassesMapper.class);
//List<HashMap<String,String>> list = table.selectAll();
//for(HashMap hm : list){
// System.out.println("-----------Midas-----------string值=" + hm.get("name") + "," + "当前类=MybatisTest.testOne()");
//}
List<Classes> aClass = cm.getClass(3);
for(Classes classes : aClass){
System.out.println("-----------Midas-----------aclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
//session.commit();
List<Classes> bClass = cm.getClass(3);
for(Classes classes : bClass){
System.out.println("-----------Midas-----------bclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
session.commit();
List<Classes> cClass = mapper.getClass(3);
for(Classes classes : cClass){
System.out.println("-----------Midas-----------bclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
//session.commit();
List<Classes> dClass = mapper3.getClass(3);
for(Classes classes : dClass){
System.out.println("-----------Midas-----------dclasses值=" + classes + "," + "当前类=MybatisTest.testOne()");
}
结果如下
==> Preparing: select * from class c RIGHT join teacher t on c.teacher_id = t.t_id where t.t_id=?
==> Parameters: 3(Integer)
<== Columns: c_id, c_name, teacher_id, t_id, t_name
<== Row: null, null, null, 3, teacher3
<== Total: 1
-----------Midas-----------aclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
Cache Hit Ratio [ClassesMapper]: 0.0
-----------Midas-----------bclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
Cache Hit Ratio [ClassesMapper]: 0.3333333333333333
-----------Midas-----------bclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
Cache Hit Ratio [ClassesMapper]: 0.5
-----------Midas-----------dclasses值=Classes{id=0, name='null', teacher=Teacher [id=3, name=teacher3], students=null},当前类=MybatisTest.testOne()
只有一次sql语句被执行。另外需要注意的是cache hit,代表缓存请求命中率。
以上是关于Mybatis小结二:映射,存储过程,缓存的主要内容,如果未能解决你的问题,请参考以下文章