Mybatis学习二

来源:互联网 发布:js input自动获取焦点 编辑:程序博客网 时间:2024/06/10 14:35

输入映射和输出映射 (自动映射和手动映射)

Sql映射文件(mapper.xml)中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

parameterType(输入类型)

1传递简单类型:使用#{}占位符,或者${}进行sql拼接。

2传递pojo对象:Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

3传递pojo包装对象:开发中通过可以使用pojo传递查询条件。

查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数

包装对象:Pojo类中的一个属性是另外一个pojo

需求1:根据用户名模糊查询用户信息,查询条件放到QueryVouser属性中

使用包装类型查询用户。

创建Mapper接口的动态代理对象,整合之后,交给spring管理。

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

创建对象,设置到包装对象中。

 

resultType(输出类型)

1)输出简单类型,输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

2)输出pojo对象

3)输出pojo集合

 

resultMap(手动映射,不是自动映射)resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可能导致对象的属性为null值。可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojolist实现一对一查询和一对多查询。

数据库表、Order对象、创建OrderMapper.xml配置文件、Mapper接口

使用resultMap:由于上边的mapper.xmlsql查询列(user_id)Order类属性(userId)不一致,所以查询结果不能映射到pojo中。

需要定义resultMap,将sql查询列(user_id)Order类属性(userId)对应起来。

 

<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">

<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->

<!-- id设置ResultMapid -->

<resultMap type="order" id="orderResultMap">

<!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->

<!-- property:主键在pojo中的属性名-->

<!-- column:主键在数据库中的列名 -->

<id property="id" column="id" />

<!-- 定义普通属性 -->

<result property="userId" column="user_id" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

</resultMap>

 

<!-- 查询所有的订单数据 -->

<select id="queryOrderAll" resultMap="orderResultMap">

SELECT id, user_id,

number,

createtime, note FROM `order`

</select>

</mapper>

 

动态sql:通过mybatis提供的各种标签方法实现动态拼接sql

需求:根据性别和名字查询用户

查询sqlSELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%%'

解决方案:使用动态sqlif标签。

<select id="queryUserByWhere" parameterType="user" resultType="user">

SELECT id, username, birthday, sex, address FROM `user`

WHERE 1=1

<if test="sex != null and sex != ''">

AND sex = #{sex}

</if>

<if test="username != null and username != ''">

AND username LIKE

'%${username}%'

</if>

</select>

注意字符串类型的数据需要要做不等于空字符串校验。

Where标签

<!-- 根据条件查询用户 -->

<select id="queryUserByWhere" parameterType="user" resultType="user">

SELECT id, username, birthday, sex, address FROM `user`

<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字-->

<where>

<if test="sex != null">

AND sex = #{sex}

</if>

<if test="username != null and username != ''">

AND username LIKE

'%${username}%'

</if>

</where>

</select>

 

Sql片段:可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

sql片段确定id,复用sql语句的目的。

把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段。

SELECT <include refid="userFields" /> FROM `user`

<!-- 使用include标签加载sql片段;refidsql片段id -->

如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xmlnamespace

 

foreach标签:向sql传递数组或Listmybatis使用foreach解析。

根据多个id查询用户信息

查询sqlSELECT * FROM user WHERE id IN (1,10,24)

<!-- 根据ids查询用户-->

<select id="queryUserByIds" parameterType="queryVo" resultType="user">

SELECT * FROM `user`

<where>

<!-- foreach标签,进行遍历 -->

<!-- collection:遍历的集合,这里是QueryVoids属性-->

<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致-->

<!-- open:在前面添加的sql片段-->

<!-- close:在结尾处添加的sql片段-->

<!-- separator:指定遍历的元素之间使用的分隔符 -->

<foreach collection="ids" item="item" open="id IN (" close=")"

separator=",">

#{item}

</foreach>

</where>

</select>

oreach循环遍历注意事项:

传递数组:array 。传递集合:list。和数据类型有关系,和变量名称没有关系的。


关联查询:连接查询(关联条件)

一对一关联查询一对多关联查询。一个用户可以有多个订单,一个订单不能归属于多个人。

需求:查询所有订单信息,关联查询下单用户信息。

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

Left join  左关联   full join全关联(求交集或者并集)  on  主外键相等(关联条件)

要查询出哪些字段?

记忆关联查询的sql语句。

以订单为中心,关联用户进行查询。把sql映射文件中的数据库语句写的工整一些。

 

单表查询,如何进行映射;多表查询,每个字段都需要进行手动映射,不能省略。

定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

使用resultMap,定义专门的resultMap用于映射一对一查询结果

<resultMap type="order" id="orderUserResultMap">

<id property="id" column="id" />

<result property="userId" column="user_id" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

 

<!-- association :配置一对一属性 -->

<!-- property:order里面的User属性名-->

<!-- javaType:属性类型 -->

<association property="user" javaType="user">

<!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->

<id property="id" column="user_id" />

<result property="username" column="username" />

<result property="address" column="address" />

</association>

 

</resultMap>

 

<!-- 一对一关联,查询订单,订单内部包含用户属性 -->

<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">

SELECT

o.id,

o.user_id,

o.number,

o.createtime,

o.note,

u.username,

u.address

FROM

`order` o

LEFT JOIN `user` u ON o.user_id = u.id

</select>

 

查询所有用户信息及用户关联的订单信息。

用户信息和订单信息为一对多关系。

附加对象集合

<resultMap type="user" id="userOrderResultMap">

<id property="id" column="id" />

<result property="username" column="username" />

<result property="birthday" column="birthday" />

<result property="sex" column="sex" />

<result property="address" column="address" />

 

<!-- 配置一对多的关系 -->

<collection property="orders" javaType="list" ofType="order">

<!-- 配置主键,是关联Order的唯一标识-->

<id property="id" column="oid" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

</collection>

</resultMap>

 

<!-- 一对多关联,查询订单同时查询该用户下的订单 -->

<select id="queryUserOrder" resultMap="userOrderResultMap">

SELECT

u.id,

u.username,

u.birthday,

u.sex,

u.address,

o.id oid,

o.number,

o.createtime,

o.note

FROM

`user` u

LEFT JOIN `order` o ON u.id = o.user_id

</select>



代码如下:

mapper接口:

package com.aowu.cn.mapper;import java.util.List;import com.aowu.cn.pojo.Order;import com.aowu.cn.pojo.QueryVo;import com.aowu.cn.pojo.User;/** * 新建接口 * @author chenrushui * */public interface UserMapper {//通过用户名进行模糊查询public List<User> selectUserByQueryVo(QueryVo vo);//查询用户表的条数public Integer countUser();//查询所有的用户数据public List<User> userList();//通过用户名和性别查询用户public List<User> selectUserByNameAndAge(User user);//通过用户名和性别查询用户    public List<User> selectUserByNameAndAgeWhere(User user);        //根据多个id查询用户信息    public List<User> selectUserByIds(List<Integer> ids);        //获取用户订单信息    public List<Order> selectOrdersList();        //获取用户所有的订单信息    public List<User> selectOrders();}

test类

package com.aowu.cn.junit;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Test;import com.aowu.cn.mapper.UserMapper;import com.aowu.cn.pojo.Order;import com.aowu.cn.pojo.QueryVo;import com.aowu.cn.pojo.User;import com.aowu.cn.pojo.UserTest;public class TestMyBatis {/** * 传入参数的类型是:pojo的包装类 *  * @throws IOException */@Testpublic void testSelectUserByQueryVo() throws IOException {// MyBatis与Spring没有整合之前的操作String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession = sqlSessionFactory.openSession();// 加载接口文件,生成动态代理文件UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setName("陈");QueryVo queryVo = new QueryVo();queryVo.setUser(user);List<User> userList = (List<User>) userMapper.selectUserByQueryVo(queryVo);for (User item : userList) {System.out.println(item);}sqlSession.close();}/** * 输出参数为简单类型 *  * @throws IOException */@Testpublic void testCountUser() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();// SqlSession帮助我们生成了一个接口的实现类UserMapper mapper = openSession.getMapper(UserMapper.class);Integer countUser = mapper.countUser();System.out.println("总的条目人数" + countUser);}/** * 查询用户表中的所有数据 对象属性和数据表字段不对应 *  * @throws IOException */@Testpublic void testUserList() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);List<User> userList = mapper.userList();for (User user : userList) {System.out.println("test:" + user.toString());}// 因为是Integer类型,数据不能自动映射,所以为0;想要显示正确的数据,需要手动映射。// 需要自动建立手动映射的信息}/** * if标签 *  * @throws IOException */@Testpublic void testIfTag() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);User userParam = new User();userParam.setAge(20);// userParam.setName("陈诗音");List<User> userList = mapper.selectUserByNameAndAge(userParam);if (userList != null && userList.size() > 0) {for (User user : userList) {System.out.println("测试对象:" + user.toString());}} else {System.out.println("测试对象:" + "没有拿到数据");}}/** * Where标签 *  * @throws IOException */@Testpublic void testWhereTag() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);User userParam = new User();// userParam.setAge(20);userParam.setName("陈诗音");List<User> userList = mapper.selectUserByNameAndAgeWhere(userParam);if (userList != null && userList.size() > 0) {for (User user : userList) {System.out.println("测试对象:" + user.toString());}} else {System.out.println("测试对象:" + "没有拿到数据");}}/** * 测试ForEach标签:根据多个id查询用户信息 用于向sql语句传递集合或者数组 *  * @throws IOException */@Testpublic void testForEachTag() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);ArrayList<Integer> list = new ArrayList<Integer>();list.add(2);list.add(3);list.add(4);QueryVo queryVo = new QueryVo();queryVo.setIds(list);List<User> userList = mapper.selectUserByIds(list);if (userList != null && userList.size() > 0) {for (User user : userList) {System.out.println("测试对象:" + user.toString());}} else {System.out.println("测试对象:" + "没有拿到数据");}}/** * 测试一对一关联 *  * @throws IOException */@Testpublic void testSelectOrdersList() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);List<Order> selectOrdersList = mapper.selectOrdersList();for (Order user : selectOrdersList) {System.out.println("test:" + user.toString());}}/* * 一对多关联映射:一个用户可能有多个订单信息 */@Testpublic void testSelectOrders() throws IOException {String path = "sqlMapConfig.xml";InputStream in = Resources.getResourceAsStream(path);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);SqlSession openSession = sqlSessionFactory.openSession();UserMapper mapper = openSession.getMapper(UserMapper.class);List<User> selectOrders = mapper.selectOrders();for (User user : selectOrders) {System.out.println(user.toString());}}}


sql映射文件:具体业务逻辑的sql语句

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace:命名空间,用于隔离sql --><!-- 对应哪个接口文件一定要搞清楚,自己在这里犯过错的 --><!-- 项目里sql映射文件存放在单独的目录里面 --><!-- Sql映射文件,每张表对应一个sql映射文件,所有对表的操作都写在sql映射文件中 --><mapper namespace="com.aowu.cn.mapper.UserMapper"><!-- 基本类型的包装类 --><select id="selectUserByQueryVo" parameterType="com.aowu.cn.pojo.QueryVo"resultType="com.aowu.cn.pojo.User">select * from user where name like "%"#{user.name}"%"</select><!-- 基本的输出参数 --><select id="countUser" resultType="Integer">select count(*) from user;</select><!-- 数据库列字段和对象属性字段不对应,需要手动映射 --><!-- <select id="userList" resultType="com.aowu.cn.pojo.User"> select * from user; </select> --><!-- 手动映射,让字段一一对应起来 --><resultMap type="com.aowu.cn.pojo.User" id="testResultMap"><result column="age" property="age_i" /></resultMap><select id="userList" resultMap="testResultMap">select * from user;</select><!-- if标签的使用,如果数据为空,就相当于去掉此判断条件 --><select id="selectUserByNameAndAge" parameterType="com.aowu.cn.pojo.User"resultType="com.aowu.cn.pojo.User">select * from userwhere age=#{age}<if test="name!=null and name!=''">and name =#{name}</if></select><!-- where标签的使用,前and是可以没有的值的,不会报错;但是如果后面的值没有就会报错 --><!-- sql片段主要用于代码的复用,id refid --><sql id="getData">select * from user</sql><select id="selectUserByNameAndAgeWhere" parameterType="com.aowu.cn.pojo.User"resultType="com.aowu.cn.pojo.User"><!-- 引用sql片段,复用代码 --><include refid="getData" /><where><if test="age!=0">age=#{age}</if><if test="name!=null and name!=''">and name =#{name}</if></where></select><!-- ForEach 标签的使用,用于向sql语句传递集合或者数组 id in (1,2,3) --><!-- 如果是数组,集合的类型就是array,必须这样写 --><select id="selectUserByIds" parameterType="com.aowu.cn.pojo.QueryVo"resultType="com.aowu.cn.pojo.User"><include refid="getData" /><where><foreach collection="list" item="id" separator="," open="id in ("close=")">#{id}</foreach></where></select><!-- 一对一关联查询:查询用户信息以及对应的订单信息 ,一个订单对应一个用户 --><!-- 手动映射:要对每一个字段进行手动赋值 --><resultMap type="com.aowu.cn.pojo.Order" id="orderList"><result column="product" property="product" /><result column="user_id" property="id" /><association property="user" javaType="com.aowu.cn.pojo.User"><result column="age" property="age" /><result column="name" property="name" /></association></resultMap><select id="selectOrdersList" resultMap="orderList">selectuser.id,user.name,user.age,user_order.user_id,user_order.productfrom user leftjoin user_orderonuser.id=user_order.user_id;</select><!--一对多关联查询,一个人可能有多个订单表信息 --><!--手动映射 --><resultMap type="com.aowu.cn.pojo.User" id="orders"><result column="id" property="id" /><result column="name" property="name" /><result column="age" property="age" /><collection property="orderList" ofType="com.aowu.cn.pojo.Order"><result column="product" property="product" /><result column="id" property="id" /></collection></resultMap><select id="selectOrders" resultMap="orders">selectuser.id,user.name,user.age,user_order.id,user_order.productfrom user left join user_orderonuser.id=user_order.user_id;</select></mapper>