MyBatis(3)MyBatis-映射文件

mac2024-11-09  8

目录

一 介绍二 主键生成方式三 参数传递单个参数多个参数命名参数POJOMap集合类型参数 四 \#和$五 resultType简单类型POJOList类型Map类型查询一条记录查询多条记录 自动映射 六 自定义resultMap范例"一对一"sql语句级联属性使用associationassociation分步查询 延迟加载(懒加载)"一对多"sql语句一次查询分步查询扩展:传递多列得值 鉴别器 参考

一 介绍

映射文件指导着MyBatis如何进行数据库增删改查,有着非常重要的意义;

cache –命名空间的二级缓存配置cache-ref – 其他命名空间缓存配置的引用。resultMap – 自定义结果集映射parameterMap – 已废弃!老式风格的参数映射sql –抽取可重用语句块。insert – 映射插入语句update– 映射更新语句delete– 映射删除语句select – 映射查询语句

二 主键生成方式

若数据库支持自动生成主键的字段(比如 MySQL和 SQL Server),则可以设置useGeneratedKeys=”true”,然后再把keyProperty 设置到目标属性上。 <insert id="insertUser" parameterType="com.zyc.entity.User" useGeneratedKeys="true" keyProperty="id"> insert into t_user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>

还可以 将insert插入的数据的主键返回到User对象中

<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select last_insert_id() </selectKey>

mysql的uuid(),实现非自增主键的返回

<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> select uuid() </selectKey> insert into t_user (id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address}) 而对于不支持自增型主键的数据库(例如Oracle),则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会`被设置·,然后插入语句会被调用 <insert id="addEmployee" databaseId="oracle"> <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> select EMPLOYEE_SEQ.nextval from dual </selectKey> <!-- 插入的主键是从序列中获取的 --> insert into employee(id,last_name,age,email) values(#{id},#{lastName},#{age},#{email}) </insert>

三 参数传递

单个参数

mybatis不会做特殊处理,#{参数名/任意名}:取出参数值(测试得:真的任意名都可以)

多个参数

mybatis会做特殊处理,多个参数会被封装成 一个map key:param1...paramN,或者arg0...argN-1

<select id="findUserById" parameterType="int" resultType="com.zyc.entity.User"> select username,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex,address from t_user where id=#{id} </select>

命名参数

明确指定封装参数时map的key;@Param("id")

public User findUserByIdAndName(@Param("id")int id, @Param("name")String name);

映射文件

<select id="findUserByIdAndName" resultType="com.zyc.entity.User"> select username,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex,address from t_user where id=#{id} and username = #{name} </select>

POJO

如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo; #{属性名}:取出传入的pojo的属性值

<select id="findUserByUser" parameterType="com.zyc.entity.User" resultType="com.zyc.entity.User"> select username,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex,address from t_user where id=#{id} </select>

Map

这个是我们自己传得map,不是上面多参数是mybatis帮我们处理得。所以可以直接通过key来获取

<select id="findUserByMap" resultType="com.zyc.entity.User"> select username,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex,address from t_user where id=#{id} </select>

集合类型参数

#{list[0]},数组就是#{array[0]}

<select id="findUserByList" resultType="com.zyc.entity.User"> select username,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex,address from t_user where id=#{list[1]} </select>

四 #和$

#{key}:获取参数的值,预编译到SQL中(因为预编译,最好用在where里面,测试发现:在编译之后加了引号)。安全。 ${key}:获取参数的值,拼接到SQL中。有SQL注入问题。

五 resultType

简单类型

<select id="getEmpNameById" resultType="string">

POJO

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。 只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。(验证通过)

<select id="findUserByMap" resultType="com.zyc.entity.User">

List类型

没什么区别 Mapper

public List<User> findUserByName(String username);

映射文件

<select id="findUserByList" resultType="com.zyc.entity.User">

Map类型

查询一条记录

将查询的数据以{表字段名, 对应的值}方式存入到Map中。

Mapper

Map<String, Object> getEmpAsMapById(Integer id);

映射文件

<select id="getEmpAsMapById" resultType="map"> select * from t_employee where id = #{id} </select>

查询多条记录

可以把查询的数据以{表中某一字段名, JavaBean}方式来封装成Map。 mapper

// 查询所有员工的信息,把数据库中的 'id' 字段作为 key,对应的 value 封装成 Employee 对象 // @MapKey 中的值表示用数据库中的哪个字段名作 key @MapKey("id") Map<Integer, Employee> getAllEmpsAsMap();

映射文件

<!-- 注意 resultType 返回值类型,不再是 'map',而是 Map 的 value 对应的 JavaBean 类型 --> <select id="getAllEmpsAsMap" resultType="employee"> select * from t_employee </select>

自动映射

全局setting设置

autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是列名和javaBean属性名一致如果autoMappingBehavior设置为null则会取消自动映射数据库字段命名规范,POJO属性符合驼峰命名法,如A_COLUMN和aColumn,我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true。

六 自定义resultMap

可以实现高级结果集映射

范例

<!--自定义某个javaBean的封装规则 type:自定义规则的Java类型 id:唯一id方便引用 --> <resultMap type="com.zyc.entity.User" id="rm1"> <!--指定主键列的封装规则 id定义主键会底层有优化; column:指定哪一列 property:指定对应的javaBean属性 --> <id column="id" property="id"/> <!-- 定义普通列封装规则 --> <result column="username" property="username"/> <!-- 其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。 --> </resultMap> <!-- resultMap:自定义结果集映射规则; --> <!-- public Employee getEmpById(Integer id); --> <select id="findUserByRm1" resultMap="rm1"> select id,username ,DATE_FORMAT(birthday,'%Y-%m-%d')birthday,sex ,address from t_user where id=#{id} </select>

“一对一”

查询Employee的同时查询员工对应的部门,就像hibernate中得一对一

sql语句

<select id="getEmpAndDept" resultMap="MyDifEmp"> SELECT e.id, e.lastname, e.gender, d.id did, d.dept_name FROM tbl_employee e, tbl_dept d WHERE e.d_id = d.id AND e.id = #{id} </select>

级联属性

<!-- 联合查询:级联属性封装结果集 --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <result column="did" property="dept.id"/> <result column="dept_name" property="dept.departmentName"/> </resultMap>

使用association

<!-- 使用association定义关联的单个对象的封装规则; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <!-- association可以指定联合的javaBean对象 property="dept":指定哪个属性是联合的对象 javaType:指定这个属性对象的类型[不能省略] --> <association property="dept" javaType="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> </association> </resultMap>

association分步查询

先按照员工id查询员工信息根据查询员工信息中的d_id值去部门表查出部门信息部门设置到员工中; <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定义关联对象的封装规则 select:表明当前属性是调用select指定的方法查出的结果 column:指定将哪一列的值传给这个方法 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性 --> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap>

延迟加载(懒加载)

主配置文件

<!-- 可以使用延迟加载(懒加载);(按需加载) Employee==>Dept: 我们每次查询Employee对象的时候,都将一起查询出来。 部门信息在我们使用的时候再去查询; 分段查询的基础之上加上两个配置: --> <settings> <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> --> <setting name="jdbcTypeForNull" value="NULL"/> <!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 --> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>

“一对多”

例如:查询部门的时候将部门对应的所有员工信息也查询出来

sql语句

<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where d_id=#{deptId} </select>

一次查询

<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> <!-- collection定义关联集合类型的属性的封装规则 ofType:指定集合里面元素的类型 --> <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee"> <!-- 定义这个集合中元素的封装规则 --> <id column="eid" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> </collection> </resultMap> <!-- public Department getDeptByIdPlus(Integer id); --> <select id="getDeptByIdPlus" resultMap="MyDept"> SELECT d.id did,d.dept_name dept_name, e.id eid,e.last_name last_name,e.email email,e.gender gender FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=#{id} </select>

分步查询

<!-- collection:分段查询 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep"> <id column="id" property="id"/> <id column="dept_name" property="departmentName"/> <collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}" fetchType="lazy"></collection> </resultMap> <!-- public Department getDeptByIdStep(Integer id); --> <select id="getDeptByIdStep" resultMap="MyDeptStep"> select id,dept_name from tbl_dept where id=#{id} </select>

扩展:传递多列得值

分步查询的时候通过column指定,将对应的列的数据传递过去,我们有时需要传递多列数据。使用{key1=column1,key2=column2…}的形式association或者collection标签的fetchType=eager/lazy可以覆盖全局的延迟加载策略,指定立即加载(eager)或者延迟加载(lazy)

鉴别器

discriminator

<!-- <discriminator javaType=""></discriminator> 鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为 封装Employee: 如果查出的是女生:就把部门信息查询出来,否则不查询; 如果是男生,把last_name这一列的值赋值给email; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- column:指定判定的列名 javaType:列值对应的java类型 --> <discriminator javaType="string" column="gender"> <!--女生 resultType:指定封装的结果类型;不能缺少。/resultMap--> <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </case> <!--男生 ;如果是男生,把last_name这一列的值赋值给email; --> <case value="1" resultType="com.atguigu.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/> </case> </discriminator> </resultMap>

参考

尚硅谷mybatis教材MyBatis查询结果resultType返回值类型详细介绍https://www.cnblogs.com/xiaoxi/p/6378960.html
最新回复(0)