mybatis中映射文件(mapper)中的使用规则
作者:北平天空
一、增删改
1、增加
<!-- 添加用户--> <insert id="saveUser" parameterType="com.tfjybj.domain.User"> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
说明:
- id属性:
映射文件中方法的唯一标识,与对应dao层中执行此功能的方法名相同。
- parameterType 属性:
代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
- sql 语句中使用#{}字符:
它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
- #{}中内容的写法:
由于参数是 一个 User 对象,此处要写 User 对象中的属性名称。这里应用了 ognl 表达式。
- ognl 表达式:
它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 对象图导航语言。它是按照 #{对象.对象}的语法格式来获取数据的,#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user,而直接写 username。
如何获得新增数据id的返回值
方式一:
mysql支持自增主键,自增主键的获取,mybatis利用了statement.getGenreatedKeys();
在< insert> 标签中添加
userGeneratedKeys=“true” :标明使用自增主键获取主键值策略。
keyProperty:指定对应的主键属性,也就是mybatis获取到主键值之后,将这个值封装给JavaScriptBean的哪个属性。
<insert id="saveUser" parameterType="com.tfjybj.domain.User" useGeneratedKeys="true" keyProperty="id"> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
方式二:
新增用户后,要求在新增数据后,将自动增长的auto_increment的值返回,mysql主键自增的返回,配置如下:
<insert id="saveUser" parameterType="com.tfjybj.domain.User"> <!-- keyColumn:要获得哪个列的值 keyProperty:查询出来的主键值封装给就AV额Bean的哪个属性 order:取值为before,当前SQL在插入SQL之前运行。取值为fater,当前SQL在插入SQL之后运行 resultType:查出的数据的返回值类型 --> <selectKey keyColumn="id" keyProperty="id" resultType="int" order="after"> select last_insert_id(); </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
2、删除
<!-- 删除用户 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{uid} </delete>
3、更新
<!-- 更新用户 --> <update id="updateUser" parameterType="com.tfjybj.domain.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex}, address=#{address} where id=#{id} </update>
注:对于增删改,我们需要手动提交数据
sqlSessionFactory.openSession(false)——默认为false即代表手动提交
二、传入参数处理
1、单个参数
mybatis不会做特殊处理,#{参数名},取出参数值。
2、多个参数
mybatis会被特殊处理,多个参数会被封装成一个map。
key :param1,param2,…paramN, 或者参数的索引也可以
value:传入的参数值
#{key} 就是从map中获取指定的key的值。
取值时,写成 #{param1},#{param2}就会不报错。
注解 @Param
而mybatis中还为我们提供了一个注解 @Param,用来将传入的参数,做一个别名处理,取值是直接使别名就能取到值:#{别名}
3、参数中有Collection(List、Set) 类型或者是数组
如果传入的参数中有Collection(List、Set) 类型或者是数组,也会特殊处理,也会吧传入的list或者数组封装到map中。
key:Collection(collection)。
如果是List还可以使用key(list)、如果是数组可以使用key(array)
4、参数封装成数据模型
如果多个参数正好是我们业务逻辑的数据模型,我们可以直接传入pojo;
#{属性名}:取出传入的pojo的属性值。
//dao层方法参数为一个pojo public Employee getEmpById(Employee employee); <!-- mapper中可直接取出属性名 --> <select id="getEmpById" resultType="com.zhyheima.mybatis.bean.Employee"> select * from tb1_employee where id=#{id} </select>
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们可以传入map
#{key}:取出map中对应的值。
5、parameterType 配置 参数
基本类型和 String 我 们可以直接写类型名称 ,也可以使用包 名 . 类名的方式 ,例如 :java.lang.String。
实体类类型,目前我们只能使用全限定类名(前提是没有在mybatis的全局配置文件中起别名)。
mybaits 在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。
三、查询
1、模糊查询
方式一:
<!-- 根据名称模糊查询 --> <select id="findByName" resultType="com.tfjybj.domain.User" parameterType="String"> select * from user where username like #{username} </select>
以上写法中没有加入%来作为模糊查询的条件,所以在程序代码中传入字符串实参时,就需要给定模糊查询的标识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”。
方式二:
<!-- 根据名称模糊查询 --> <select id="findByName" parameterType="string" resultType="com.tfjybj.domain.User"> select * from user where username like '%${value}%' </select>
将原来的#{}占位符,改成了$ {value}。注意如果用模糊查询的这种写法,那么$ {value}的写法就是固定的,不能写成其它名字。这样在程序代码中就不需要加入模糊查询的匹配符%了。
2、#{}与${}的区别
#{} 表示一个占位符号
通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。
$ {} 表示拼接 sql 串
通过$ {}可以将 parameterType 传入的内容拼接在 sql中且不进行 jdbc 类型转换, $ {}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,$ {}括号中只能是 value。
大多数情况下,我们去参数的值都应该去使用#{};
3、返回属性为resultType
resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。
- 若返回的是一个List集合,则resultType中写这个集合中的类型即可。
- 若返回的是一个Map集合(查询一条数据),则mybatis中的resultType中可以直接写小map。
- 若返回的是一个Map集合(查询多条数据,每条数据的model作为value),则mybatis中用这个model作为返回类型,并且在dao层返回的Map声明上加上注解@MapKey(“要作为key的字段名”)
对于实体类型,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。
同时,当是实体类名称时,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
4、返回属性为resultMap
若mybatis中查询出的数据列与bean中的属性无法对应上(名称不对应),解决办法:
- sql查询的时候,查询出的字段用as 后面加一个别名。
- 在全局配置文件中,使用settings设置,支持驼峰命名法。(mybatis在window系统下不区分字母大小写,若数据库中字段名为lastname,javabean中的属性名称为lastName,则可以查询成功)。
- mybatis中使用resultMap作为返回,resultMap可以自定义结果映射规则。
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
自定义某个javaBean的封装规则
resultMap属性:
- type 属性:指定实体类的全限定类名
- id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
内部标签:
- id 标签:用于指定主键字段
- result 标签:用于指定非主键字段
- column 属性:用于指定数据库列名
- property 属性:用于指定实体类属性名称
<!-- 建立 User 实体和数据库表的对应关系 type 属性:指定实体类的全限定类名 id 属性:给定一个唯一标识,是给查询 select 标签引用用的。 --> <resultMap type="com.zhyheima.domain.User" id="userMap"> <id column="id" property="userId"/> <result column="username" property="userName"/> <result column="sex" property="userSex"/> <result column="address" property="userAddress"/> <result column="birthday" property="userBirthday"/> </resultMap> <!-- 配置查询所有操作 --> <select id="findAll" resultMap="userMap"> select * from user </select>
联合查询,实体级联属性封装结果集(一对一或多对一)
一对一:对于查询结果中,是两个model的集合,即一个model嵌套了一个model,比如查询被雇佣者的信息,并根据该信息查询出雇主的信息,返回被雇佣者和雇主两个model的信息。
多对一:雇佣者可能有多个,但只有一个雇主。
使用asscociation联合查询,定义实体级联属性封装规则(一对一或多对一)
resultMap中还可以使用association标签,进行一对一查询。
进行分步查询,使用asscociation联合查询,定义实体级联属性封装规则(一对一或多对一)
分步查询,先查询被雇佣者的信息,在根据被雇佣者查询雇佣者信息。被分为了两个sql语句。
使用collection嵌套结果集(一对多或多对多)
例如:
查询所有用户信息及用户关联的账户信息。
用户信息和他的账户信息为一对多关系。
<resultMap type="com.zhyheima.bean.user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/> <result column="address" property="address"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <!-- collection 是用于建立一对多中集合属性的对应关系 ofType 用于指定集合元素的数据类型 --> <collection property="accounts" ofType="com.zhyheima.bean.account"> <id column="aid" property="id"/> <result column="uid" property="uid"/> <result column="money" property="money"/> </collection> </resultMap> <!-- 配置查询所有操作 --> <select id="findAll" resultMap="userMap"> select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid </select>
collection
部分定义了用户关联的账户信息。表示关联查询结果集。
property=“accounts” :
关联查询的结果集存储在 User 对象的上哪个属性。
ofType=“com.zhyheima.bean.account” :
指定关联查询的结果集中的对象类型即List中的对象类型。
同样collection也支持分布查询,具体查询方式和association的方式一样。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。