一、映射器简介
1.什么是mapper动态代理?
在接口中有方法的返回值定义,参数的定义,方法名,在sqlMapper.xml 中也对应这接口给予了赋值, 这时候dao的实现类就显得多余,这是Mybatis可以帮助我们自动产生实现类,并可以调取方法得到结 果,这就是Mybatis的mapper动态代理
2.动态代理的规范
Mapper接口开发需要遵循以下规范:
- 接口中的返回值 要和 sqlMapper 中的resultType 一致
- 接口中的入参 要和 sqlMapper 中的parameterType 一致
- 接口的方法名 要和 sqlMapper 中的id 一致(dao层不允许方法的重载)
- sqlMapper 中的namespace 指向 接口的类路径
- 接口要和sqlMapper 同包
- 接口要和sqlMapper 同名
3.如何使用动态代理
使用SqlSession的方法getMapper() 让Mybatis自动生成对应接口的实现对象。
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> sList = new ArrayList<Student>();
sList = mapper.findAllAtudent();
for(Student student:sList) {System.out.println(student);
}
DaoUtil.closeResource(sqlSession);
selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用 selectList方法,如果返回单个对象则调用selectOne方法。
namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入 参数可以使用pojo包装对象或map对象,保证dao的通用性。
4.为什么学习映射器
半自动化的体现 | 配置 SQL 语句,体现了半自动化和灵活性。 |
ORM的体现 | 对象关系映射的实现,数据库表 和 POJO 类的映射关系。 |
5.映射器与接口
映射器配置文件和接口绑定:配置文件名对应接口名,id 属性值对应方法名。
6.映射器的引入
文件路径 | 用相对路径引入映射器: |
<mapper resource=”com/codeup/dao/Mapper.xml”/> | |
XML | 用文件定位符引入映射器: |
<mapper url=”file:///var/mappers/Mapper.xml”/> | |
包名 | 用包名引入映射器: |
<package name=”com.codeup.dao.Mapper”/> | |
类注册 | 用类名引入映射器: |
<mapper class=”com.codeup.mapper.NewsMapper”/> |
7.映射器的组成
映射器 | ||||||
SQL语句 | 映射关系 | |||||
<select> | <insert> | <delete> | <update> | <sql> | <parame terMap> | <result Map> |
二、s e l e c t 元素
语法规则: < select 属性=“值”>查询类SQL语句</select>
属性 | 说明 |
id | 唯一标识,接口中的方法名; |
parameterType | 入参的类型; |
resultType | 结果的类型; |
resultMap | 复杂的结果集映射关系; |
<select id="findAllAtudent" resultType="Student"> select * from student
</select>
1.输出简单类型
定义接口方法:
//查询所有学生
public List<Student> findAllAtudent();
在StudentMapper.xml中写对应标签和sql语句:
<select id="findAllAtudent" resultType="Student"> select * from student
</select>
2.参数传递
XML 文件中:配置文件中利用 parameterType 属性设置参数类型,利用 #{}设置参数的使用及位置。
接口中:接口中,按照方法的入参方式指定参数类型和参数名称。
条件有 > < >= <= 可以使用转义字符进行代替:
//接口:
//查看sid大于num的学生
public List<Student> findStudentBigSid(int num);
xml文件:
<select id="findStudentBigSid" parameterType="int" resultType="student">select * from student where sid < #{v}
</select>
3.多个参数传递
//查询 某个班某个性别的学生 ,mybatis 只能传一个参
传递多参的方式一:javaBean对象
//传递多参的方式一:javaBean对象//接口:
public List<Student> findStudentByClassAndSsex(Student s);
xml文件:
<select id = "findStudentByClassAndSsex" parameterType="Student" resultType="Student">select * from student where classid = #{classid} and ssex = #{ssex}
</select>
//传递多参的方式二:Map(不推荐,耦合度太高)
//传递多参的方式二:Map(不推荐,耦合度太高)//接口:
public List<Student> findStudentByClassidAndSsexLimit(Map<String,Object> map);
xml文件:
<select id="findStudentByClassidAndSsexLimit" parameterType="map" resultType="Student">select * from student where classid = #{bj} and ssex = #{xb} limit #{wz},#{bc}
</select>
//传递多参的方式三:param数 数从1开始 推荐
//传递多参的方式三:param数 数从1开始 推荐//接口:
public List<Student> findStudentByClassidAndSsexLimitParam(int classid,String ssex,int weizhi,int buchang);
xml文件:
<select id="findStudentByClassidAndSsexLimitParam">select * from student where classid = #{param1} and ssex = #{param2} limit #{param3},#{param4}
</select>
//传递多参的方式四:arg数 数是从0开始 --> 和后面框架内置参数的名称
//传递多参的方式四:arg数 数是从0开始 --> 和后面框架内置参数的名称//接口:
public List<Student> findStudentByClassidAndSsexLimitArg(int classid,String ssex,int weizhi,int buchang);
xml文件:
<select id="findStudentByClassidAndSsexLimitArg" resultType="Student">select * from student where classid = #{arg0} and ssex = #{arg1} limit #{arg2},#{arg3}
</select>
三、i n s e r t 元素
语法规则: < insert 属性=“值”>新增类SQL语句</insert>
属性 | 说明 |
id | 唯一标识,接口中的方法名; |
parameterType | 参数的类型; |
keyProperty | 表示以哪个列作为属性的主键,不能和 keyColumn 同时使用; |
keyColumn | 指明哪一列是主键,不能和 keyProperty 同时使用; |
useGeneratedKeys | 使用 JDBC 的 getGeneratedKeys 方式来取有数据库内部生成的主键; |
1.主键回填
功能 当主键在数据库中为自增字段时,新增成功后,回填主键。
useGeneratedKeys="true" 开启主键回填
keyProperty="sid" 回填的主键给哪个属性
//接口:
public int addStudent(Student s);
useGeneratedKeys="true" 开启主键回填keyProperty="sid" 回填的主键给哪个属性//xml文件:
<insert id="addStudent" parameterType="com.ape.bean.Student"useGeneratedKeys="true" keyProperty="sid">insert into student (sname,birthday,ssex,classid)values(#{sname},#{birthday},#{ssex},#{classid})
</insert>
2.自定义主键生成规则
<selectKey> :用来预先设定主键值。自定义主键生成规则时,可以使用该标签;
order 属性: 取值 BEFORE,AFTER ;
四、u p d a t e 元 素 和 d e l e t e 元素
1.<update>
语法规则: < update 属性=“值”>查询类SQL语句</update>
属性 | 说明 |
id | 唯一标识,接口中的方法名; |
parameterType | 参数的类型; |
2.<delete>
语法规则: < delete 属性=“值”>查询类SQL语句</delete>
属性 | 说明 |
id | 唯一标识,接口中的方法名; |
parameterType | 参数的类型; |
五、r e s u l t M a p 元 素
1.为什么要使用 resultMap 元素
01 定义映射规则 | ORM 的特性,POJO 类和数据 库的映射关系; |
02 级联操作 | 多表存在主外键关系时,主表和 从表之间的关联操作; |
03 类型转换 | 数据库字段的类型和 POJO 类 属性的类型转换 |
2.resultMap 元素的结构
<constructor>:用于配置构造方法的元素
<id>:标识主键列,允许多个主键。
<result>:POJO 到 SQL 列名的映射关系。
3.使用 POJO 存储结果集
xml文件:
<!-- sqlMapper 文件:执行方法和sql语句映射-->
<mapper namespace="com.zad.mapper.StudentMapper"><resultMap type="student" id="stu_class_Map"><result column="sid" property="sid" /><result column="sname" property="sname" /><result column="birthday" property="birthday" /><result column="ssex" property="ssex" /><result column="classid" property="classid" />
</mapper>
属性 | 说明 |
property | 映射到列结果的字段或者属性,通常是指 POJO 的属性; |
column | 对应的数据库字段; |
javaType | Java 类型,可以是基本数据类型,也可以是类完全限定名; |
jdbcType | JDBC 的类型,基本支持所有常用的数据库类型; |
六、多表联查
1.什么是级联
级联(cascade),是指多个对象之间的映射关系,建立数据之间的级联关系提高管理效率
一对一 :一个对象对应唯一的对象, 举例:中国公民和身份证;
一对多 :一个对象对应多个对象, 举例:班级和学生;
多对多 :多个对象对应多个对象, 举例:公司角色和公司员工
2.一对一级联步骤
- 验证 编写测试类验证级联关系;
- 级联映射 利用 元素完 成一对一级联;
- 创建映射器 创建对应的映射器;
- 创建关联POJO 一对一级联时,以对象方式存 储关联关系;
3.一对一级联映射
首先在实体类中添加级联表的对象:
public class Student {private int sid;private String sname;private Date birthday;private String ssex;private int classid;//外部属性private Banji bj;
//接口
public List<Student> findAllStudent();
//xml文件:
<mapper namespace="com.zad.mapper.StudentMapper"><resultMap type="student" id="stu_class_Map"><result column="sid" property="sid" /><result column="sname" property="sname" /><result column="birthday" property="birthday" /><result column="ssex" property="ssex" /><result column="classid" property="classid" /><!-- 一对一 --><association property="bj"><result column="classid" property="classid" /><result column="classname" property="classname" /></association></resultMap><select id="findAllStudent" resultMap="stu_class_Map">select * from studentleft join class on student.classid = class.classid</select>
</mapper>
4.一对多级联步骤
创建”一“方POJO 以集合的形式级联“多”方对象
创建“多”方对象 创建“多”方的 POJO 对象
创建映射器 创建对应的映射器
实现一对多级联 利用 collection 元素实现一 对多的级联
测试 编写测试文件测试一对多级联
5.一对多级联
首先在实体类中添加级联表的对象list集合:
public class Banji {private int classid;private String classname;// 外部属性private List<Student> stulist;
//接口
public List<Banji> findAllBanjiAndStu();
//xml文件:
<mapper namespace="com.zad.mapper.BanjiMapper">
<!-- 类路径 --><resultMap type="Banji" id="bj_class_Map"><result column="classid" property="classid"/><result column="classname" property="classname"/><!-- 1对多 --><collection property="stulist" ofType="Student"><result column="sid" property="sid"/><result column="sname" property="sname"/><result column="birthday" property="birthday"/><result column="ssex" property="ssex"/><result column="classid" property="classid"/></collection></resultMap><select id="findAllBanjiAndStu" resultMap = "bj_class_Map">select * from classleft join student on class.classid = student.classid</select>
</mapper>
6.级联的缺陷
- 性能缺陷 级联操作会降低性能, 增加程序的执行时间;
- 复杂度缺陷 关联较多造成复杂度的 增加,不利于他人的理 解和维护
使用建议:
1、根据实际情况增加级联关系;
2、多层关联式,建议超过三层关联时尽量少用级联;