-
什么是MyBatis?
MyBatis是支持普通SQL查询存储过程和高级映射的优秀持久层框架,MyBatis几乎消除了所有JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的xml或注解用于配置和原始映射,将接口和java的POJOs、普通的java对象映射为数据库的记录。 -
MyBatis中“#”和 $ 的区别
1.#相当于加上双引号(参数化处理),$ 相当于直接显示数据(拼接)
2.#将传入的数据都当成一个字符串,会对自动传入的数据加入双引号.如order by #id#,如果传入的值为12,那么解析成sql时为order by “12”
3.$ 将传入的数据直接显示生成在sql中,如order by $ id $ ,如果传入的值为12,那么解析成sql时为order by id
4.#方式能很大程度上避免sql注入,而$不能
5 $ 方式一般用于传入数据库对象,如传入表名、列名 -
MyBatis中Sql
- < select>元素
<!--根据学生id查询学生信息--!>
<select id="selectStudentsBySid" parameterType="int"
resultType="Students">
select * from students where sid = #{sid}
</select>
<!--id的值是唯一标识符,它接收一个int类型的参数,返回一个Students类型对象--!>
2.< insert>元素
<!--插入一个学生信息--!>
<insert id="addStudents" parameterType="Students">
insert into students
values(null,#{sname},#{age},#{gid});
</insert>
3.< update>元素
<!--更新一个学生信息--!>
<insert id="addStudents" parameterType="Students">
insert into students
values(null,#{sname},#{age},#{gid});
</insert>
4.< delete>元素
<!--根据学生id删除学生信息--!>
<delete id="deleteStudentsBySid" parameterType="int">
delete from students where sid=#{sid}
</delete>
5.< if>元素
<!-- 动态sql if的使用 -->
<select id="selectStudentsByWhere" parameterType="Students" resultType="Students">
select * from students
<where>
<if test="sname!=null">
sname=#{sname}
</if>
<if test="gid!=0">
and gid=#{gid}
</if>
</where>
</select>
6.< choose>、< when>、< otherwise>元素
<select id="selectStudentsByChoose" parameterType="Students" resultType="Students">
select *from students
<where>
<choose>
<when test="sname!=null">
sname=#{sname}
</when>
<when test="gid!=0">
and gid=#{gid}
</when>
<otherwise>
and age>18
</otherwise>
</choose>
</where>
</select>
7.< set>元素
<!--动态sql set的使用 -->
<update id="updateStudents1" parameterType="Students">
update students
<set>
<if test="sname!=null">
sname=#{sname},
</if>
<if test="age!=0">
age=#{age},
</if>
<if test="gid!=0">
gid=#{gid}
</if>
</set>
where sid=#{sid}
</update>
8.< foreach>元素
<!-- 动态sql foreach的使用 -->
<select id="selectStudents2" resultType="Students">
select * from students where sid in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<!--foreach 传递的参数是map时 -->
<select id="selectStudents4" resultType="Students">
select * from students where sid in
<!--sids指的是传递进来的map中的key值 -->
<foreach item="item" index="index" collection="sids" open="(" separator="," close=")">
#{item}
</foreach>
and sname like "%"#{keyword}"%"
</select>
- 级联查询
1.一对一级联查询
<!--连接查询 -->
<select id="selectStudentsAndGrade" resultMap="StudentsMap">
select * from students inner join grade on students.gid=grade.gid
</select>
<resultMap type="Students" id="StudentsMap">
<id property="sid" column="sid"/><!--property:指定映射到实体的对象属性 column:指定表中对应的字段-->
<result property="sname" column="sname"/>
<result property="age" column="age"/>
<!--association 使用在一对一或多对一的关系 代表一个学生对应一个班级 -->
<!--javaType:指定映射到实体对象属性的类型--!>
<association property="grade" javaType="Grade">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
</association>
</resultMap>
<!--嵌套查询 -->
<select id="selectStudentsAndGrade2" resultMap="StudentsMap2">
select * from students
</select>
<select id="selectGradeByGid" parameterType="int" resultType="Grade">
select * from grade where gid=#{gid}
</select>
<resultMap type="Students" id="StudentsMap2">
<!--如果表中字段名和对象属性名是一致的 id result这些组装标签可以省略 -->
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="age" column="age"/>
<!--select指定引入嵌套查询的子SQL语句,用于嵌套查询--!>
<association property="grade" column="gid" select="selectGradeByGid">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
</association>
</resultMap>
2.一对多级联查询
<!--连接查询 -->
<select id="selectGradeAndStudent" parameterType="int" resultMap="GradeMap">
select * from grade inner join students on grade.gid=students.gid and grade.gid=#{gid}
</select>
<resultMap type="Grade" id="GradeMap">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
<!--ofType表示集合中的元素类型 -->
<collection property="studentsList" ofType="Students">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="age" column="age"/>
<association property="grade" javaType="Grade">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
</association>
</collection>
</resultMap>
<!--一对多关系 方式2:嵌套查询 -->
<select id="selectGradeAndStudents2" parameterType="int" resultMap="GradeMap2">
select * from grade where gid=#{gid}
</select>
<select id="selectStudentsBySid" parameterType="int" resultType="Students">
select * from students where gid=#{gid}
</select>
<resultMap type="Grade" id="GradeMap2">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
<collection property="studentsList" column="gid" select="selectStudentsBySid">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="age" column="age"/>
<association property="grade" javaType="Grade">
<id property="gid" column="gid"/>
<result property="gname" column="gname"/>
</association>
</collection>
</resultMap>
- MyBatis延迟加载
1.什么是延迟加载
resultMap中association和collection标签具有延迟加载的功能,即在关联查询时,利用延迟加载,先加载主信息,使用关联信息时才去加载关联信息
在mybatis.xml中配置
<setting name="lazyLoadingEnabled" value="true"/>
<!--设置是否是积极的懒加载 false代表按需加载,true代表加载同级别的所有属性 -->
<setting name="aggressiveLazyLoading" value="false"/>
- 一级缓存和二级缓存
一级缓存
1.一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于缓存数据。不同的SqlSession之间的数据缓存区域是互不影响的
一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕将会将数据库中查询的数据写到缓存,第二次查询会从缓存中获取数据,不去底层数据库查询,提高查询效率,当SqlSession执行了增删改并提交到数据库,MyBatis会轻空SqlSession中的一级缓存,当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。关闭一级缓存后,再次访问,需要再次获取一级缓存,然后才能查找数据,否则会抛出异常。
2.二级缓存
二级缓存是mapper级别的缓存。多个SqlSession使用同一个Mapper的sql语句取操作数据库,得到的数据会存在二级缓存区域,二级缓存是跨SqlSession的,二级缓存的作用域是mapper的同一个namespace。