一、注解配置
目前MyBatis支持注解配置,用注解方式来替代映射文件,但是注解配置还是有点不完善,在开发中使用比较少,大部分的企业还是在用映射文件来进行配置。
不完善的地方体现在于当数据表中的字段名与实体对象的属性名不一致时,需要配置ResultMap,但是注解的配置只能是在方法前,也就是当前方法能使用这个配置,其他的方法是不能应用此注解配置的ResultMap。
注解配置的方式是直接在数据访问接口的方法前加上相应的注解
@select(“select * from student ”)
public List<Student> find();
在MyBatis的主配置文件的mappers节点中注册所有的数据持久化接口类
案例:
数据持久化接口
public interface SubjectDao {
@Select("select * from subject")
@Results({ //字段名与属性名不一致
@Result(id=true,column="subjectNo",property="id"), //主键
@Result(column="subjectName",property="subjectName"),
@Result(column="classHour",property="hour")
})
public List<Subject> find();
}
MyBatis主配置文件的mappers节点配置
<!-- 如果有映射时,对映射文件进行配置 -->
<mappers>
<!-- 加载单个映射文件,允许映射文件与持久接口类不在同一目录下。 -->
<mapper resource="com/icss/mapping/AdminDao.xml"/>
<mapper resource="com/icss/mapping/GradeDao.xml"/>
<mapper resource="com/icss/mapping/StudentDao.xml"/>
<!-- 注解配置时,需要在主配置文件中注册数据持久化接口类 -->
<mapper class="com.icss.dao.SubjectDao"/>
<!-- 加载这个包中的所有映射文件,要求持久化接口与映射文件必须在同一个目录中 -->
<!-- <package name="com.icss.dao"/> -->
</mappers>
当表中的数据行有一对多或多对一的映射关系时的处理方式
一对多:
//一对多 : many
@Select("select * from grade")
@Results(
{
@Result(id=true, column="gradeId",property="gradeId"),
@Result(column="gradeName", property="gradeName"),
@Result(column="gradeId",property="subjects",
many=@Many(select = "com.etc.dao.SubjectDao.findSubjectByGradeId"))
}
)
public List<Grade> find();
多对一:
@Select("select * from subject")
@Results({
@Result(id=true,column="subjectNo",property="id"),
@Result(column="subjectName",property="subjectName"),
@Result(column="classHour",property="hour"),
//多对一的情况操作,根据年级编号调用年级的数据持久化接口的方法,返回一个年级对象存储在grade这个属性中。
@Result(column="gradeId",property="grade",one=@One(select="com.icss.dao.GradeDao.getGradeById"))
})
public List<Subject> find();
数据持久化层代码:
package com.icss.dao;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import com.icss.entity.Subject;
public interface SubjectDao {
@Select("select * from subject")
@Results({
@Result(id=true,column="subjectNo",property="id"),
@Result(column="subjectName",property="subjectName"),
@Result(column="classHour",property="hour"),
//多对一的情况操作,根据年级编号调用年级的数据持久化接口的方法,返回一个年级对象存储在grade这个属性中。 @Result(column="gradeId",property="grade",one=@One(select="com.icss.dao.GradeDao.getGradeById"))
})
public List<Subject> find();
//根据年级查询课程
@Select("select * from subject where gradeId=#{id}")
@Results({
@Result(id=true,column="subjectNo",property="id"),
@Result(column="subjectName",property="subjectName"),
@Result(column="classHour",property="hour"),
//多对一的情况操作,根据年级编号调用年级的数据持久化接口的方法,返回一个年级对象存储在grade这个属性中。 @Result(column="gradeId",property="grade",one=@One(select="com.icss.dao.GradeDao.getGradeById"))
})
public List<Subject> findByGID(int id);
//新增
@Insert("insert into subject(null,#{subjectName},#{hour},#{grade.gradeId})")
public int add(Subject subject);
//删除
@Delete("delete from subject where subjectNo=#{id}")
public int delete(int id);
//修改
@Update("update subejct set subjectName=#{subjectName},classHour=#{hour},"
+ " gradeId=#{grade.gradeId} where subjectNo=#{id}")
public int update(Subject subject);
}
在团队开发中,建议统一用其中的一种处理方式,用注解就全部用注解,用映射文件就统一用映射文件。
二、模糊查询
错误的处理方法:
<!-- 字段与属性名不一致,不能用resultType属性 -->
<select id="getStudents" resultMap="studentMap" parameterType="map">
select * from student
<if test="name != null">
where name like '%'+#{name}+'%'
</if>
</select>
正确的方式是在参数传入之前就加了这些通配符。
sqlSession = SqlSessionFactoryUtil.getsqlSession();
StudentDao dao= sqlSession.getMapper(StudentDao.class);
//参数传入到映射文件前就加了模糊查询的通配符
Map<String, String> map = new HashMap<>();
map.put("name", "%张%");
//调用方法,执行查询
list=dao.getStudents(map);
映入文件如下:
<!-- 字段与属性名不一致,不能用resultType属性 -->
<select id="getStudents" resultMap="studentMap" parameterType="map">
select * from student
<if test="name != null">
where name like #{name}
</if>
</select>
三、动态SQL
MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力,也是MyBatis最有特色的地方,就是它的动态SQL,解决了我们多条件时SQL指令的拼接问题。查询学生信息:条件可能(姓名,年龄,年级,性别,地址)
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。 动态SQL非常简单,与JSTL的使用非常类似。
if:当条件成立时,则把内部的SQL拼接到外部的SQL指令中。
<!-- 字段与属性名不一致,不能用resultType属性 -->
<select id="getStudents" resultMap="studentMap" parameterType="map">
select * from student
<if test="name != null">
where name like #{name}
</if>
</select>
choose, when, otherwise:
这是一个多重if-else结构,如果只有一个when和otherwise,则可以认为是if-else结构
select–>choose–>otherwise
<!-- 字段与属性名不一致,不能用resultType属性 -->
<select id="getStudents" resultMap="studentMap" parameterType="map">
select * from student
<choose>
<when test="name != null">
where name like #{name}
</when>
<otherwise>
where age > #{age}
</otherwise>
</choose>
</select>
where:
当条件比较多的时候,要进行条件拼接,where的作用是进行条件拼接,自动加上where 关键字,而且会把多余的and 或 or 这些连接关键字去掉。
select-->where-->if
<!-- 字段与属性名不一致,不能用resultType属性 -->
<select id="getStudents" resultMap="studentMap" parameterType="map">
select * from student
<where>
<if test="name != null">
and name like #{name}
</if>
<if test="age != null">
and age > #{age}
</if>
</where>
</select>
拼接后的SQL: select * from student where (and) name like ‘%张%’ and age > 22
set: 用于修改的SQL指令
在修改的SQL指令中自动加上set关键字,同时把多余的逗号(,)去掉。非常适合修改部分值
update–>set–>if
<update id="update" parameterType="map">
update student
<set>
<if test="name != null">
name=#{name},
</if>
<if test="age != null">
age=#{age},
</if>
<if test="sex != null">
sex=#{sex},
</if>
<if test="phone != null">
phone=#{phone}
</if>
</set>
where studentNo=1002
</update>
拼接后的SQL:
update student set name=‘肖月月’,age=20,sex=‘女’ where studentNo=1002
foreach
这个动态 SQL 通用的必要操作是迭代一个集合, 通常是构建在 IN 条件中.
<select id="getStudents1" resultMap="studentMap" parameterType="list">
select * from student where address in
<foreach item="s" collection="list" open="(" close=")" separator=",">
#{s}
</foreach>
</select>
业务层处理:
sqlSession = SqlSessionFactoryUtil.getsqlSession();
StudentDao dao= sqlSession.getMapper(StudentDao.class);
List<String> arr = new ArrayList<String>();
arr.add("广州市");
arr.add("深圳市");
//调用方法,执行查询
list=dao.getStudents1(arr);