java mybatis sql 查询耗时_MyBatis第二天(结果映射+动态sql+关联查询)

笑不出莱:MyBatis第一天(介绍+文件配置+Mapper动态代理)​zhuanlan.zhihu.com
zhihu-card-default.svg

一、导包+配置文件+pojo类

1、jar包:mybatis的核心包和依赖包+连接数据库的jar包

2、日志文件(可以不需要)

3、SqlMapConfig.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<!--给trd.mybatis.pojo包下的所有类取别名(为简单类名且首字母大小写不敏感) -->
	<typeAliases>
		<package name="trd.mybatis.pojo"/>
	</typeAliases>
	
	<!-- 和spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="a123" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 加载trd.mybatis.mapper包下的所有映射文件(映射文件名有限制) -->
	<mappers>
		<package name="trd.mybatis.mapper"/>
	</mappers>
</configuration>

4、pojo类

// 用户pojo类,对应用户表
package trd.mybatis.pojo;

import java.util.Date;
import java.util.List;

public class User {

	private int id;
	private String username;
	private Date birthday;
	private String sex;
	private String address;
	// 一个用户能有多个订单
	private List<Orders> orderList;	
}
//=============================================================================
// 订单pojo类,对应订单表
package trd.mybatis.pojo;

import java.util.Date;

public class Orders {

	// oid和uid没有和Orders表的对应列的名字一样,是为了测试(resultMap)手动映射
	private int oid; // id
	private int uid; // user_id
	
	private String number;
	private Date createtime;
	private String note;
	// 一个订单归属于一个用户
	private User user;		
}
//============================================================================
// 复杂pojo类,嵌套了其他pojo
package trd.mybatis.pojo;

import java.util.Arrays;
import java.util.List;

public class UserWrapper {

	private User user;
        // 测试foreach遍历
	private int[] intArr;
	private List<Integer> integerList;
}

二、结果映射(resultMap)

  1. 作用:pojo类属性名和数据库中查询结果名不同时,用resultMap来手动映射
  2. 注意:当resultMap只映射简单pojo类时(也就是此时pojo类不存在嵌套其他pojo或者不存在集合),resultMap里可以只写出不同名的属性,其余同名的属性会自动进行映射
	<!--
		type:映射到哪一个pojo
		id:为该resultMap的唯一id,用来被需要用到它的地方所引用
	-->
	<resultMap type="Orders" id="mapOrder">
		<!-- 
			id标签:定义主键 ,非常重要。如果是多个字段,则定义多个id
			result标签:定义普通属性
			————column属性:数据库中的列名(查询出的结果)
			————property属性:对应pojo中的属性名
		-->
		<id column="id" property="oid"/>
		<result column="user_id" property="uid"/>
	</resultMap>
	<select id="findAllInOrders" resultMap="mapOrder">
		SELECT * FROM orders
	</select>

三、动态sql

(只测试了常用的where,if,foreach。而choose, when, otherwise类似java中的switch,when对应case,otherwise对应default,且用的相对少,就没有测试)

1、where+if

(1)where标签:有sql子句的情况下才会插入where。而且,若整个sql语句的开头为 and 或者是 orwhere 元素也会将它们去除

(2)if标签:test属性值是判断的条件

<!-- 抽取出重复的sql片段,使用include标签引用它,可以达到重用的目的 -->
<sql id="selectSql">
	select * from user
</sql>
<!--===================================================================================-->
<select id="findUserByCriteria" parameterType="User" resultType="User">
	<include refid="selectSql"/>
	<where>
		<if test="id != null and id != '' ">
			and id = #{id}
		</if>
		<if test="username != null and username != '' ">
			and username = #{username}
		</if>
	</where>
</select>

2、foreach(遍历标签,构建IN条件语句时用的多)

属性介绍:

  1. collection可迭代的对象可以直接是数组,集合(此时collection属性值就是array和list),也可以是包装在pojo类中的数组和集合(这时用包装类对应的的引用属性)
  2. item本次迭代获取的元素
  3. open:在前面添加的sql片段
  4. close:在结尾处添加的sql片段
  5. separator:指定遍历的元素之间使用的分隔符
<select id="findUserById" resultType="User" parameterType="UserWrapper">
	<include refid="selectSql"/>
	<where>				
		<!-- 参数为封装在pojo类中的集合 -->
		<!-- <foreach collection="integerList" item="id" open=" id IN(" separator="," close=")">
			#{id}
		</foreach> -->
		
		<!-- 参数为集合 -->
		<!-- <foreach collection="list" item="id" open=" id IN(" separator="," close=")">
			#{id}
		</foreach> -->
		
		<!-- 参数为数组 -->
		<foreach collection="array" item="id" open=" id IN(" separator="," close=")">
			#{id}
		</foreach>
	</where>
</select>

四、关联查询

1、原始的DBUtils解决多表关联查询:

将多表查询的结果用MapListHandler(一行对应一个map(键为列名),许多map又被封装进一个list集合中)封装起来,遍历这个list集合,在利用beanUtils工具将每个map封装为简单的javabean(多个),再将这些javabean进行对应的嵌套

2、MyBatis解决多表关联查询(用resultMap):

(1)一对一:一个pojo里面嵌套了另一个pojo

(1.1) association标签:关联一个复杂类型(比如pojo)

属性介绍:

  • javaType:指定关联的这个复杂类型的java类型
  • property:pojo中对应的属性名

(1.2) mapper的配置

<!--  ==================一对一查询,订单表对应用户表(订单表为中心)============== -->
<resultMap type="Orders" id="order">
	<id column="orders_id" property="oid"/>
	<result column="note" property="note"/>
	<result column="number" property="number"/>
	<result column="createtime" property="createtime"/>
	<association property="user" javaType="trd.mybatis.pojo.User">
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		<result column="address" property="address"/>
	</association>
</resultMap>
<select id="findOrdersInMultilist" resultMap="order">
	SELECT 
	u.username,
	u.address,
	o.user_id,
	o.id  AS  orders_id,
	o.number,
	o.createtime,
	o.note
	FROM  `user` u  RIGHT JOIN  orders o 
	ON   u.id=o.user_id
</select>

(1.3) 数据库的查询结果

1da2ee08f552596d813aaebba5116209.png

(2)一对多:一个pojo里面嵌套了集合的pojo

(2.1)collection标签:关联一个复杂类型的集合

属性介绍:

  • ofType:这个复杂类型集合里装的对象的具体类型
  • property:pojo中对应的属性名

(2.2) mapper的配置

<!-- ==================	一对多查询,用户表对应订单表(用户表为中心)	============= -->
<resultMap type="user" id="user">
	<id column="user_id" property="id"/>
	<result column="username" property="username"/>
	<result column="address" property="address"/>
		
	<!-- 属性说明(其余的和上面一样):
		ofType:集合装的对象的具体类型
	-->
	<collection property="orderList" ofType="orders">
		<id column="orders_id" property="oid"/>
		<result column="note" property="note"/>
	</collection>
</resultMap>
<select id="findUserInMultilist" resultMap="user">
	SELECT 
	u.username,
	o.id AS orders_id,
	o.user_id,
	o.number,
	o.createtime,
	o.note,
	u.address
	FROM `user` u  LEFT JOIN  orders o 
	ON  u.id=o.user_id
</select>

(2.3) 数据库的查询结果

279549141b6f79876a48f26b3fae3b04.png

(3)注意:

存在pojo嵌套时,数据库中查出来的列的名字和pojo中属性名相同时,也不能省略。

五、Mapper接口+测试类

1、映射文件对应的接口

package trd.mybatis.mapper;

import java.util.List;

import trd.mybatis.pojo.Orders;
import trd.mybatis.pojo.User;
import trd.mybatis.pojo.UserWrapper;

public interface UserMapper {

	// 测试resultMap
	List<Orders> findAllInOrders();	
	
	// 动态sql语句值if
	User findUserByCriteria(User user);	
	// 动态sql之foreach
	List<User> findUserById(int[] intArr);
	List<User> findUserById(UserWrapper wrapper);
	List<User> findUserById(List<Integer> integerList);
	
	// 多表查询
	List<Orders> findOrdersInMultilist();
	List<User> findUserInMultilist();
}

2、测试类

package trd.mybatis.test;

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.Before;
import org.junit.Test;

import trd.mybatis.mapper.UserMapper;
import trd.mybatis.pojo.Orders;
import trd.mybatis.pojo.User;
import trd.mybatis.pojo.UserWrapper;

public class Test1 {

	private InputStream is = null;
	private SqlSessionFactoryBuilder builder = null;
	private SqlSessionFactory factory = null;
	private SqlSession sqlSession = null;
	
	// 每次junit测试前调用,来给私有属性赋值
	@Before
	public void before() throws IOException{
		is = Resources.getResourceAsStream("sqlMapConfig.xml");
		builder = new SqlSessionFactoryBuilder();
		factory = builder.build(is);
		sqlSession = factory.openSession();
	}
	
	// 测试查询所有订单(用resultMap手动映射)
	@Test
	public void findAllInOrders() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		List<Orders> ordersList = mapper.findAllInOrders();
		for (Orders orders : ordersList) {
			System.out.println(orders);
		}
	}
	
	// 测试动态sql的if标签
	@Test
	public void findUserByCriteria() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		User user = new User();
//		user.setId(1);
		user.setUsername("小强");
		User user2 = mapper.findUserByCriteria(user);
		System.out.println(user2);
	}
	
	// 测试动态sql的foreach标签(参数为其他pojo类)
	@Test
	public void findUserById1() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		UserWrapper wrapper = new UserWrapper();
		List<Integer> integerList = new ArrayList<Integer>();
		integerList.add(1);
		integerList.add(10);
		integerList.add(25);
		wrapper.setIntegerList(integerList);
		List<User> userList = mapper.findUserById(wrapper);
		for (User user : userList) {
			System.out.println(user);
		}
	}
	
	// 测试动态sql的foreach标签(参数为List集合)
	@Test
	public void findUserById2() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		List<Integer> integerList = new ArrayList<Integer>();
		integerList.add(1);
		integerList.add(10);
		integerList.add(25);
		List<User> userList = mapper.findUserById(integerList);
		for (User user : userList) {
			System.out.println(user);
		}
	}	
	
	// 测试动态sql的foreach标签(参数为数组)
	@Test
	public void findUserById3() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		int[] intArr = new int[]{1,10,25,6595,5};
		List<User> userList = mapper.findUserById(intArr);
		for (User user : userList) {
			System.out.println(user);
		}
	}
	
	// 测试多表查询中的一对一查询(一份订单只能对应一个用户)
	@Test
	public void findOrdersInMultilist() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		List<Orders> ordersList = mapper.findOrdersInMultilist();
		for (Orders orders : ordersList) {
			System.out.println(orders);
		}
	}
	
	// 测试多表查询中的一对多查询(一个用户对应多份订单)
	@Test
	public void findUserInMultilist() throws IOException{
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		List<User> userList = mapper.findUserInMultilist();
		for (User user : userList) {
		        System.out.println(user);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值