resultMap和缓存
参数
方法一:#{参数}
例如:
<!--会创建PreparedStatement对象,可以使用占位符,并通过占位符安全地设置参数,可以防止sql语句注入,安全性能更高-->
如:select * from student where id=#{id}
转换为:select * from student where id=?
<!--numericScale保留小数点的位数-->
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}//设置其他的参数
方法二:${参数}
如:select * from student order by ${name}
转换为:select * from student order by '张三'
<!--${name}会被直接替换,通常用来替换表名,sql语句容易注入-->
resultMap
作用
用于解决属性名与列名不一致
解决复杂的查询语句
简单的resultMap
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
高级映射
两个方面:第一,站在多的一方,其二站在一的一方
association(多对一)
一个复杂类型的(关联);许多结果将包装成这种类型
嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
方法一:
<resultMap id="baseStudentClasses" type="Student">
<id property="id" column="id"></id>
<result property="name" column="sname"/>
<association property="classer" javaType="commons.entity.Classer">
<result column="classesName" property="classesName"/>
</association>
</resultMap>
<select id="selectAll" resultMap="baseStudentClasses">
select
s.id,s.name as sname,c.id,c.classesName
from student s inner join classes c on s.classesid=c.id
</select>
方法二:
<resultMap id="baseStudentClasses" type="Student">
<id property="id" column="id"></id>
<result property="name" column="name"/>
<association property="classer" javaType="commons.entity.Classer" select="sellctCAll" column="classesid">
</association>
</resultMap>
<select id="selectAll" resultMap="baseStudentClasses">
select * from student
</select>
<select id="sellctCAll" resultType="commons.entity.Classer" parameterType="int">
select * from classes where id=#{id}
</select>
collection(一对多)
一个复杂类型的集合
嵌套结果映射 – (集合)可以是 resultMap 元素,或是对其它结果映射的引用
方法一:
<resultMap id="baseClassesStudent" type="commons.entity.Classer">
<id property="id" column="cid"></id>
<result property="classesName" column="classesName"></result>
<collection property="claStu" ofType="Student">
<id column="id" property="id"/>
<result property="id" column="sname"/>
</collection>
</resultMap>
<select id="classesByIdStu" resultMap="baseClassesStudent">
select
s.id,s.name as sname,c.id as cid,c.classesName
from student s inner join classes c on s.classesid=c.id where c.id=#{id}
</select>
方法二:
<resultMap id="baseClassesStudent" type="commons.entity.Classer">
<id property="id" column="cid"></id>
<result property="classesName" column="classesName"></result>
<collection property="claStu" ofType="Student" javaType="ArrayList" select="sellctCAll" column="cid">
<id column="id" property="id"/>
<result property="id" column="sname"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="baseStudentClasses">
select * from student
</select>
<select id="sellctCAll" resultType="commons.entity.Classer" parameterType="int">
select * from classes where id=#{id}
</select>
缓存
会话缓存(一级缓存)
特点:会话缓存是默认自动开启的,会话关闭即清除缓存
例如:
SqlSession sqlSession = BaseDao.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
for (int i=0;i<3;i++) {
List<Classer> classer = mapper.classesByIdStu(1);
}
<!--最终输出一句sql语句-->
sqlSession.close();
SqlSession sqlSession = BaseDao.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
for (int i=0;i<3;i++) {
//注意这里
List<Classer> classer = mapper.classesByIdStu(i);
}
//最终输出三句sql语句
sqlSession.close();
for (int i=0;i<3;i++) {
SqlSession sqlSession = BaseDao.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Classer> classer = mapper.classesByIdStu(1);
sqlSession.close();
}
//最终输出三句sql语句
总结:第一个sql语句并没有被改变,所以可以直接从会话里拿到,第二个,sql语句已经发生的改变,那么就会重新在数据库中查询,第三个,会话关闭即清理缓存
二级缓存
在同一个命名空间下,会话关闭后,sql语句没有改变的情况下,是从二级缓存下取到的sql语句
步骤:
1.在mybatis-config.xml文件中加入属性:
<settings>
<!-- 是否开启缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2.在StudentMapper.xml文件中加入标签
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
3:实体类需要连接接口
public class Classer implements Serializable {
//代码
}
4.测试
for (int i=0;i<3;i++) {
SqlSession sqlSession = BaseDao.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Classer> classer = mapper.classesByIdStu(1);
sqlSession.close();
}
//最终输出一句sql语句
原因:第一次的时候,查询数据库,查询完成之后关闭会话,此时sql语句已经进入到了二级缓存,在第二次查询的时候,直接从二级缓存里面拿取