zoukankan      html  css  js  c++  java
  • mybatis笔记02

    0. 文章目录

    • Mybatis映射文件

    • 动态SQL

    • 关联查询

    1. Mybatis映射文件

    • 映射文件中select的两个参数重要参数:parameter和resultType

    • parameter: 输入映射,定义输入到sql中的映射类型,${value}表示使用参数将${value}替换,做字符串拼接。如果是取简单数量类型的参数,括号中的值必须为value。

    • resultType: 输出映射,定义结果映射类型。

    1.1 输入映射

    • 输入映射支持的数据类型:

      • 基本数据类型:基础类型以及包装类、String
      • POJO
      • Map
      • 包装的POJO:一个pojo中有pojo属性
    • 输入映射参数为map类型举例

      案例预览

      /mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.xml

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.itzhouq.mybatis.mapper.UserMapper">
      	<!-- statementId -->
      	<select id="findById" parameterType="int" resultType="com.itzhouq.mybatis.pojo.User" >
      		select * from user where id = #{id}
      	</select>
      	
      	<insert id="insertUser" parameterType="com.itzhouq.mybatis.pojo.User">
      		<selectKey resultType="int" keyProperty="id" order="AFTER">
      			<!-- 返回当前事务最后产生的id值 -->
      			SELECT LAST_INSERT_ID();
      		</selectKey>
      		insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address});
      	</insert>
      	<select id="findUserByMap" parameterType="map" resultType="com.itzhouq.mybatis.pojo.User">
      		select * from user where username like '%${username}%' and sex = #{sex} and address=#{address}
      	</select>
      	
      </mapper>
      
      

      /mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.java

      package com.itzhouq.mybatis.mapper;
      
      import java.util.List;
      import java.util.Map;
      
      import com.itzhouq.mybatis.pojo.User;
      
      public interface UserMapper {
      	public User findById(int id);
      	
      	public void insertUser(User user);
      	//映射参数为map类型
      	public List<User> findUserByMap(Map<String, Object> map);
      }
      
      

      /mybatis-day02/src/com/itzhouq/mybatis/test/UserMapperTest.java

      package com.itzhouq.mybatis.test;
      
      import java.io.IOException;
      import java.util.HashMap;
      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.Before;
      import org.junit.Test;
      
      import com.itzhouq.mybatis.mapper.UserMapper;
      import com.itzhouq.mybatis.pojo.User;
      
      public class UserMapperTest {
      	SqlSessionFactory sqlSessionFactory = null;
      	@Before
      	public void init() throws IOException {
      		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      		sqlSessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));
      	}
      	
      	@Test
      	public void testFindById() {
      		SqlSession sqlSession = sqlSessionFactory.openSession();
      		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      		User user = mapper.findById(28);
      		System.out.println(user);
      		sqlSession.close();
      	}
      	
      	@Test
      	public void testFindByMap() {
      		SqlSession sqlSession = sqlSessionFactory.openSession();
      		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      		HashMap<String, Object> map = new HashMap<String, Object>();
      //		select * from user where username like '%张%' and sex = '1' and address='河南郑州'
      //		select * from user where username like '%${username}%' and sex = #{sex} and address=#{address}
      		map.put("username", "张");
      		map.put("sex", "1");
      		map.put("address", "河南郑州");
      		
      		List<User> users= mapper.findUserByMap(map);
      		System.out.println(users);
      		sqlSession.close();
      	}
      	
      }
      
      
      • 测试testFindByMap得到两个user对象

      • 输入映射参数为包装的POJO类型举例

      在pojo中新建一个类QueryVo

      /mybatis-day02/src/com/itzhouq/mybatis/pojo/QueryVo.java

      package com.itzhouq.mybatis.pojo;
      
      public class QueryVo {
      	private User user;
      
      	public User getUser() {
      		return user;
      	}
      	public void setUser(User user) {
      		this.user = user;
      	}
      }
      

      接口中/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.java

      package com.itzhouq.mybatis.mapper;
      
      import java.util.List;
      import java.util.Map;
      
      import com.itzhouq.mybatis.pojo.QueryVo;
      import com.itzhouq.mybatis.pojo.User;
      
      public interface UserMapper {
      	public User findById(int id);
      	
      	public void insertUser(User user);
      	//映射参数为map类型
      	public List<User> findUserByMap(Map<String, Object> map);
      	//映射参数为包装的POJO类型
      	public List<User> findUserByQueryVo(QueryVo queryVo);
      
      }
      

      测试文件中/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.xml添加

      
      	<select id="findUserByQueryVo" parameterType="queryVo" resultType="user">
      	<!-- queryVo
      			user
      				username -->
      		select * from user where username like '%${user.username}%'
      	</select>
      

      测试类/mybatis-day02/src/com/itzhouq/mybatis/test/UserMapperTest.java

      @Test
      	public void testFindByQueryVo() {
      		SqlSession sqlSession = sqlSessionFactory.openSession();
      		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      		QueryVo queryVo = new QueryVo();
      		User user = new User();
      		user.setUsername("张");
      		queryVo.setUser(user);
      		List<User> users= mapper.findUserByQueryVo(queryVo);
      		System.out.println(users);
      		sqlSession.close();
      	}
      

    1.2 输出映射

    • 输出映射支持的数据类型:

      • 基本数据类型:基础类型以及包装类、String
      • POJO
      • Map
      • List
    • 输出映射参数为map类型举例

      接口com.itzhouq.mybatis.mapper.UserMapper

      package com.itzhouq.mybatis.mapper;
      
      import java.util.List;
      import java.util.Map;
      
      import com.itzhouq.mybatis.pojo.QueryVo;
      import com.itzhouq.mybatis.pojo.User;
      
      public interface UserMapper {
      	public User findById(int id);
      	public void insertUser(User user);
      	//映射参数为map类型
      	public List<User> findUserByMap(Map<String, Object> map);
      	//映射参数为包装的POJO类型
      	public List<User> findUserByQueryVo(QueryVo queryVo);
      	//输出映射类型为int型
      	public int findUserCount();
      	//输出映射参数为map类型
      	public Map findById2(int id);
      	
      }
      

      映射配置文件/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.xml中添加

      <select id="findUserCount" resultType="int">
      		select count(*) from user;
      </select>
      

      测试类

      @Test
      	public void testFindById2() {
      		SqlSession sqlSession = sqlSessionFactory.openSession();
      		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      		Map map = mapper.findById2(28);
      		System.out.println(map);
      		//{birthday=2019-04-09, address=芭蕉洞, sex=0, id=28, username=玉面狐狸}
      		sqlSession.close();
      	}
      

    1.3 resultMap

    resultMap作用:当实体类的属性名和表的字段名不一致时,需要手动映射。

    复制数据库中的user表为user_copy1,更改其中的username和sex字段,这时候这两个字段和实体类User中的属性名就不一致了。

    更改后的表和类需要正常映射的话,需要手动配置resultMap

    <resultMap id="findById3ResultMap" type="user">
        <id column="id" property="id"/>
        <result column="user_name" property="username"/>
        <result column="gender" property="sex"/>
        <!-- <result column="birthday" property="birthday"/>
      <result column="address" property="address"/> -->
    </resultMap>
    
    <select id="findById3" parameterType="int" resultMap="findById3ResultMap" >
        select * from user_copy1 where id = #{id}
    </select>
    
    • 字段相同的列可以省略不用手动配置

    2. 动态SQL

    2.1 if和where

    • 需求分析:实际开发过程中,会用到组合条件查询,条件的个数是不固定的,这就要求sql语句中的条件根据传入的参数动态改变。为此,mybatis引入了where和if标签产生动态sql。

    • 示例:

      UserMapper.java文件中添加一个方法

      //动态Sql
      public List<User> findListByUser(User user);
      

      xml配置文件

      <select id="findListByUser" parameterType="user" resultType="user">
          select * from user
          <where>
              <if test="username!=null and username!=''">
                  username like '%${username}%'
              </if>
              <if test="sex!=null and sex!=''">
                  and sex = #{sex}
              </if>
              <if test="address!=null and address!=''">
                  and address=#{address}
              </if>
          </where>
      </select>
      	
      
      • if作用:判断
      • where作用:取出第一个and或者or

      测试

      @Test
      public void testFindListByUser() {
          SqlSession sqlSession = sqlSessionFactory.openSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          User user = new User();
          //		user.setUsername("张");
          user.setSex("1");
          user.setAddress("河南郑州");
          List<User> list= mapper.findListByUser(user);
          System.out.println(list);
          sqlSession.close();
      }
      

      mybatis可以根据user中条件个数动态生成sql语句

      比如上面代码中两个条件下,生成的sql语句为:

      DEBUG [main] - ==>  Preparing: select * from user WHERE sex = ? and address=? 
      

    2.2 foreach循环

    • 需求分析:要查询用户id为1 16 22 的用户信息,相对应的sql语句为 SELECT * FROM user where id in (1, 16, 22)。查询的参数是数组,把这个数组放在包装类中传递。

      接口文件中添加

      //动态sql,foreach循环
      public List<User> findListByArray(QueryVo queryVo);
      

      包装类中添加数组ids

      package com.itzhouq.mybatis.pojo;
      
      public class QueryVo {
          private User user;
      
          int[] ids;
      
          public int[] getIds() {
              return ids;
          }
          public void setIds(int[] ids) {
              this.ids = ids;
          }
          public User getUser() {
              return user;
          }
          public void setUser(User user) {
              this.user = user;
          }
      }
      
      

      映射配置文件

      <select id="findListByArray" parameterType="queryVo" resultType="user">
          <!-- queryVo -->
          <!-- ids = [ 1, 16, 22] -->
          <!-- SELECT * FROM `user` where id in (1, 16, 22) -->
          <!-- select * from user where id in -->
          SELECT * FROM `user` where id in 
          <foreach collection="ids" open="(" close=")" separator="," item="id">
              #{id}
          </foreach>
      </select>
      

      测试类

      @Test
      public void testFindListByArray() {
          SqlSession sqlSession = sqlSessionFactory.openSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          QueryVo queryVo = new QueryVo();
          int[] ids = {1, 16, 22};
          queryVo.setIds(ids);
          List<User> list= mapper.findListByArray(queryVo);
          System.out.println(list);
          sqlSession.close();
      }
      

      生成的sql语句

      DEBUG [main] - ==>  Preparing: SELECT * FROM user where id in ( ? , ? , ? ) 
      

    2.3 sql片段 sql+include

    • sql片段主要是用于xml文件中的代码复用

      <select id="findListByUser" parameterType="user" resultType="user">
          select * from user
          <include refid="findUserWhere"></include>
      </select>
      <sql id="findUserWhere">
          <where>
              <if test="username!=null and username!=''">
                  username like '%${username}%'
              </if>
              <if test="sex!=null and sex!=''">
                  and sex = #{sex}
              </if>
              <if test="address!=null and address!=''">
                  and address=#{address}
              </if>
          </where>
      </sql>
      

    2.4 set

    • 需求分析:在更新数据库操作时,有可能只是更改某几个字段,传递的数据类型为user时,如果user的某些属性没有赋值,相当于把这些数据库中的这些字段设为null或者默认值,这样不符合我们的需求。这就需要判断user中的属性是否为空了。但是结合sql语句,修改操作时,每个字段后面又一个逗号。这里需要需要使用set去掉逗号,保证生成sql语句的正确性。

      接口代码

      //动态sql,set
      public void updateUser(User user);
      

      映射文件中添加

      <update id="updateUser" parameterType="user">
          <!-- update user set username=#{username},sex=#{sex},
         birthday=#{birthday},address=#{address} where id=#{id} -->
          update user
          <set>
              <if test="username != null and username != ''">
                  username=#{username},
              </if>
              <if test="sex != null and sex != ''">
                  sex=#{sex},
              </if>
              <if test="birthday != null">
                  birthday=#{birthday},
              </if>
              <if test="address != null and address != ''">
                  address=#{address},
              </if>
          </set>
          where id=#{id}
      </update>
      

      测试类

      @Test
      public void testUpdateUser() {
          SqlSession sqlSession = sqlSessionFactory.openSession();
          UserMapper mapper = sqlSession.getMapper(UserMapper.class);
          User user = new User();
          user.setId(28);
          user.setUsername("铁扇公主");
          mapper.updateUser(user);
          sqlSession.commit();
          sqlSession.close();
      }
      

      生成的sql语句

      DEBUG [main] - ==>  Preparing: update user SET username=? where id=? 
      

    4. 关联查询

    4.1 商品订单数据模型

    商品订单数据模型

    4.2 一对一查询

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

    4.2.1 方法一:

    • 使用resultType,定义订单信息pojo类,此pojo类中包括了订单信息和用户信息。

    • sql语句

      select o.*,u.username,u.address,u.birthday,u.sex from orders o left join user u on o.user_id = u.id
      
    • 新建pojo类,OrdersUser,这个类中应该包括sql查询出来的所有字段

      public class OrdersUser {
          private int id;
          private int user_id;
          private String number;
          private Date createtime;
          private String note;
          private String username;// 用户姓名
          private String sex;// 性别
          private Date birthday;// 生日
          private String address;// 地址
          public int getId() {
              return id;
          }
          public void setId(int id) {
              this.id = id;
      

      • OrdersMapper.xml文件
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.itzhouq.mybatis.mapper.OrdersMapper">
          <!-- statementId -->
          <select id="findOrdersUserList" resultType="ordersUser" >
              select o.*,u.username,u.address,u.birthday,u.sex from
              orders o left join user u on o.user_id = u.id
          </select>
      </mapper>
      

      • 测试类OrdersMapperTest.java
      package com.itzhouq.mybatis.test;
      
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      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.Before;
      import org.junit.Test;
      
      import com.itzhouq.mybatis.mapper.OrdersMapper;
      import com.itzhouq.mybatis.mapper.UserMapper;
      import com.itzhouq.mybatis.pojo.OrdersUser;
      import com.itzhouq.mybatis.pojo.QueryVo;
      import com.itzhouq.mybatis.pojo.User;
      
      public class OrdersMapperTest {
          SqlSessionFactory sqlSessionFactory = null;
          @Before
          public void init() throws IOException {
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              sqlSessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));
          }
      
          @Test
          public void testFindOrdersUserList() {
              SqlSession sqlSession = sqlSessionFactory.openSession();
              OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
              List<OrdersUser> ordersUserList = mapper.findOrdersUserList();
              System.out.println(ordersUserList);
              sqlSession.close();
      
          }
      }
      
      

      查询结果与数据库中相同

      结果

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

    4.2.2 方法2:

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

      select o.*,u.username,u.address,u.birthday,u.sex from orders o left join user u on o.user_id = u.id
      
      • 定义pojo类:早Orders类中加入Users属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一的关系,所以这使用单个User对象存储关联查询的用户信息。

        public class Orders {
            private int id;
            private int user_id;
            private String number;
            private Date createtime;
            private String note;
        
            private User user;
        
            public int getId() {
                return id;
            }
        

      • 映射文件OrdersMapper.xml

        <resultMap id="ordersResultMap" type="orders" >
            <id column="id" property="id"/>
            <result column="user_id" property="user_id"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            <!-- 构建一对一级联关系 -->
            <association property="user" javaType="com.itzhouq.mybatis.pojo.User">
                <id column="user_id" property="id"/>
                <result column="username" property="username"/>
                <result column="address" property="address"/>
                <result column="birthday" property="birthday"/>
                <result column="sex" property="sex"/>
            </association>
        </resultMap>
        
        <select id="findOrdersList" resultMap="ordersResultMap" >
            select o.*,u.username,u.address,u.birthday,u.sex from
            orders o left join user u on o.user_id = u.id
        </select>
        

        这里resultMap指定ordersResultMap。

      :表示进行关联查询的单条记录

      property:表示关联查询到结果存储在com.itzhouq.mybatis.pojo.User中

      javaType:表示关联查询的结果类型

      :查询结果的user_id列对象关联对象的id属性,这里是表示user_id是关联对象的唯一标识。


      • OrdersMapper接口
      public interface OrdersMapper {
          public List<OrdersUser> findOrdersUserList();
      
          public List<Orders> findOrdersList();
      }
      

      • 测试

        @Test
        public void testFindOrdersList() {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
            List<Orders> ordersList = mapper.findOrdersList();
            System.out.println(ordersList);
            sqlSession.close();
        }
        

      • 总结:使用association完成关联查询,将关联查询信息映射到pojo对象中。

    4.3 一对多查询

    • 案例:查询所有用户信息及用户相关联的订单信息

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

    • sql语句

    • 定义pojo类:在User中添加

      public class User implements Serializable {
          private int id;
          private String username;// 用户姓名
          private String sex;// 性别
          private Date birthday;// 生日
          private String address;// 地址
      
          private List<Orders> ordersList;
      

    • 映射文件OrdersMapper.xml

      <resultMap type="user" id="UserResultMap">
          <id column="id" property="id"/>
          <result column="username" property="username"/>
          <result column="address" property="address"/>
          <result column="birthday" property="birthday"/>
          <result column="sex" property="sex"/>
          <!-- public List<User> findUserList(); -->
          <!-- collection:一对多关联,ofType集合中包含的属性 -->
          <collection property="ordersList" ofType="com.itzhouq.mybatis.pojo.Orders">
              <id column="oid" property="id"/>
              <result column="id" property="user_id"/>
              <result column="number" property="number"/>
              <result column="createtime" property="createtime"/>
              <result column="note" property="note"/>
          </collection>
      </resultMap>
      <select id="findUserList" resultMap="UserResultMap">
          select u.*,o.id oid,o.number,o.createtime,o.note from user u 
          inner join orders o on o.user_id = u.id
      </select>
      
      collection部分定义了用户关联的订单信息。表示关联查询结果集
      property="orders":关联查询的结果集存储在User对象的上哪个属性。
      ofType="orders":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
      <id />及<result/>的意义同一对一查询。
      

    • 接口

      public interface OrdersMapper {
          public List<OrdersUser> findOrdersUserList();
      
          public List<Orders> findOrdersList();
          //查询User,User中关联多个订单
          public List<User> findUserList();
      }
      

    • 测试

      @Test
      public void testFindUserList() {
          SqlSession sqlSession = sqlSessionFactory.openSession();
          OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
          List<User> userList = mapper.findUserList();
          System.out.println(userList);
          sqlSession.close();
      }
      
      • 结果与数据库中查询的结果一致。
  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/itzhouq/p/mybatis2.html
Copyright © 2011-2022 走看看