mybatis入门三

上一篇学习了mybatis使用ognl表达式解析对象字段值,#{}、${}括号中为pojo属性值;其实在开发中都是通过传入pojo对象去操作更多的业务的,今天使用pojo包装对象。

先有一个包装类QueryVo,包装类有User对象

输入映射和输出映射
parameterType输入类型
package cn.itcast.mybatis.pojo;
//包装对象
public class QueryVo {	
	private User user;
	public QueryVo() {
		super();
	}
	public QueryVo(User user) {
		super();
		this.user = user;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

定义UserMapper接口

package cn.itcast.mybatis.mapper;

import java.util.List;

import cn.itcast.mybatis.pojo.QueryVo;
import cn.itcast.mybatis.pojo.User;

public interface UserMapper {
	
	/**
	 * 根据id查询用户
	 * 
	 * @param id
	 * @return
	 */
	public User queryUserById(int id);

	/**
	 * 根据用户名模糊查询数据
	 * 
	 * @param username
	 * @return
	 */
	public List<User> queryUserByUsername(String username);

	/**
	 * 新增用户
	 * 
	 * @param user
	 */
	public void saveUser(User user);

	/**
	 * 根据包装对象查询用户数据
	 * 
	 * @param queryVo
	 * @return
	 */
	public List<User> queryUserByQueryVo(QueryVo queryVo);

	/**
	 * 查询用户数据总记录数
	 * 
	 * @return
	 */
	public int queryUserCount();

	/**
	 * 根据性别和用户名查询用户
	 * 
	 * @param user
	 * @return
	 */
	public List<User> queryUserBySexAndUsername(User user);

	/**
	 * 根据多个id查询用户
	 * 
	 * @param queryVo
	 * @return
	 */
	public List<User> queryUserByIds(QueryVo queryVo);

	/**
	 * 查询用户数据,包含订单数据
	 * 
	 * @return
	 */
	public List<User> queryUserOrder();
}

同包名下的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">
<!-- 
	namespace:mapper.xml和接口命名一样
 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
	<!-- 
		parameterType:参数类型为QueryVo  接口所传的参数 
		resultType:返回类型
	 -->
	<select id="queryUserByQueryVo" 
		parameterType="QueryVo" resultType="user" >
			SELECT * FROM USER WHERE username LIKE '%${user.username}%'
	</select>
</mapper>

SqlMapConfig.xml配置

事物、数据库、mapper扫描配置

<?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>
	<!-- 设置别名 -->
	<typeAliases>
		<package name="cn.itcast.mybatis.pojo"/>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<!-- 使用JDBC事物管理 -->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 数据连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<!-- 使用包扫描方式 -->
		<package name="cn.itcast.mybatis.mapper"/>
	</mappers>
</configuration>

测试Test

public class UserMapperTest {
	
	private SqlSessionFactory sqlSessionFactory;
	
	@Before
	public void init() throws Exception{
		SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();
		InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
		this.sqlSessionFactory = sessionFactoryBuilder.build(inputStream);
	}
	
	@Test
	public void queryUserByQueryVoTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		UserMapper userMapper = openSession.getMapper(UserMapper.class);
		QueryVo queryVo = new QueryVo();
		User user = new User();
		user.setUsername("测");
		queryVo.setUser(user);
		List<User> list = userMapper.queryUserByQueryVo(queryVo);
		for (User user2 : list) {
			System.out.println(user2);
		}
	}
}

测试结果:

User [id=28, username=测试用户01, sex=男, birthday=null, address=bj]
User [id=29, username=测试02, sex=女, birthday=null, address=bj]
User [id=30, username=测试02, sex=女, birthday=null, address=bj]
resultType输出类型

输出简单类型,查询用户条数

UserMapper.xml

<!-- 查询用户数据总记录数
		  输出类型为int
	 -->
	<select id="queryUserCount" parameterType="User" resultType="int">
		SELECT COUNT(*) FROM USER
	</select>

测试:

@Test
	public void queryUserCountTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		UserMapper userMapper = openSession.getMapper(UserMapper.class);
		int count = userMapper.queryUserCount();
		System.out.println(count);  openSession.colse();//关闭链接,跟spring整合后可以交给spring
	}

结果:

3

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

resultMap

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功(可以参考第一天)

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

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

使用resultMap

创建OrderMapper接口与OrderMapper配置wen

package cn.itcast.mybatis.pojo;

import java.util.Date;

public class Order {
	// 订单id
	private int id;
	// 用户id
	private Integer userId;
	// 订单号
	private String number;
	// 订单创建时间
	private Date createtime;
	// 备注
	private String note;

	//get/set省略
}
package cn.itcast.mybatis.mapper;
import java.util.List;
import cn.itcast.mybatis.pojo.Order;
public interface OrderMapper {	
	/**
	 * 查询所有订单数据
		 * @return
	 */
	public List<Order> queryOrderAll();


	/**
	 * 查询订单数据,包含用户信息
		 * @return
	 */
	public List<Order> queryOrderUserResultMap();
}

OrderMapper.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="cn.itcast.mybatis.mapper.OrderMapper">
	<!-- resultMap最终要映射到pojo上,type是指定到那个pojo上的 -->
	<!-- 因为sqlMapConfig配置mapper扫描pojo  配置typeAliases别名 不区分大小写 -->
	<resultMap type="order" id="orderResultMap">
		<!-- column:主键在数据库列名 property为pojo属性名 -->
		<id column="id" property="id"/>
		<result column="user_id" property="userId"/>
		<result column="number" property="number"/>
		<result column="createtime" property="createtime"/>
		<result column="note" property="note"/>
	</resultMap>
	
	<select id="queryOrderAll" resultMap="orderResultMap">
		SELECT id, user_id,
		number,
		createtime, note FROM `order`
	</select>
</mapper>

测试

	@Test
	public void queryOrderAllTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		OrderMapper orderMapper = openSession.getMapper(OrderMapper.class);
		List<Order> list = orderMapper.queryOrderAll();
		for (Order order : list) {
			System.out.println(order);
		}
	}
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Order [id=1, userId=28, number=10000001, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
Order [id=2, userId=28, number=10000002, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
Order [id=3, userId=29, number=10000003, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
动态SQL

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

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

        /**
	 * 根据条件查找用户信息
	 * @return
	 */
	public List<User> queryUserByWhere(User user);
<select id="queryUserByWhere" parameterType="user" resultType="user">
			SELECT id, username, birthday, sex, address FROM `user`
				WHERE sex = #{sex} AND username LIKE '%${username}%'
	</select>

测试

@Test
	public void queryUserByWhereTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		OrderMapper orderMapper = openSession.getMapper(OrderMapper.class);
		User user = new User();
		user.setUsername("01");
		user.setSex("男");		
		List<User> userByWhere = orderMapper.queryUserByWhere(user);
		for (User orderUser : userByWhere) {
			System.out.println(orderUser);
		}
	}
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
User [id=28, username=测试用户01, sex=男, birthday=null, address=bj]

如果注释掉  user.setSex("男"),是肯定查不出来的,如果按之前学的,需要编写多个sql,显然不靠谱了

解决方案,使用动态sql的if标签

	<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>

结果

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
User [id=28, username=测试用户01, sex=男, birthday=null, address=bj]

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

还可以改造where

<select id="queryUserByWhere" parameterType="user" resultType="user">
			    SELECT id, username, birthday, sex, address FROM `user`			
			<where>
				<if test="sex != null and sex != ''">
					AND sex = #{sex}
				</if>
				<if test="username != null and username != ''">
					AND username like '%${username}%'
				</if>
			</where>
</select>
SQL片段

sql中重复的sql提取出来,使用include引用

<select id="queryUserByWhere" parameterType="user" resultType="user">
			<!-- 使用include加载sql片段  -->
			SELECT <include refid="userFields"></include> FROM `user`
			<where>
				<if test="sex != null and sex != ''">
					AND sex = #{sex}
				</if>
				<if test="username != null and username != ''">
					AND username like '%${username}%'
				</if>
			</where>
	</select>
	
	<sql id="userFields">
		id, username, birthday, sex, address
	</sql>
forEach标签

根据多个id查询用户信息

改造QueryVo包装类

package cn.itcast.mybatis.pojo;

import java.util.List;

//包装对象
public class QueryVo {
	private User user;
	
	//根据多个id查询
	private List<Integer> ids;

	//get/set方式省略
}

UserMapper.xml

<select id="queryUserByIds" parameterType="queryVo" resultType="user">
		<!-- 
			forech标签,进行遍历
			collection:是遍历集合,这里是queryVo里面的ids属性
			item:遍历变量,可以随便写
			open:在前面添加的sql片段
			close:在结尾处添加的sql片段
			separator:指定遍历的元素之间使用的分隔符
		 -->
		SELECT
		<include refid="userFields" />
		FROM user
		<where>
			<!-- collection:拼接sql所遍历的集合 -->
			<!-- item:遍历集合的遍历,可以写任意的名字 -->
			<!-- open:拼接的sql是什么开头 -->
			<!-- close:拼接的sql是什么结尾 -->
			<!-- separator:sql语句中条件的分隔符 -->
			<foreach collection="ids" item="item" open="id IN (" close=")"
				separator=",">
				#{item}
			</foreach>
		</where>
	</select>
	
	<!-- 声明sql片段 -->
	<!-- id:就是sql片段的唯一标识符 -->
	<sql id="userFields">
		id, username, birthday, sex, address
	</sql>

测试

@Test
	public void queryUserByIdsTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		UserMapper userMapper = openSession.getMapper(UserMapper.class);		
		QueryVo queryVo = new QueryVo();
		ArrayList<Integer> arrayList = new ArrayList<>();
		arrayList.add(28);
		arrayList.add(30);
		queryVo.setIds(arrayList);
		List<User> list = userMapper.queryUserByIds(queryVo);
		for (User user : list) {
			System.out.println(user);
		}
	}

结果:

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
User [id=28, username=测试用户01, sex=男, birthday=null, address=bj]
User [id=30, username=测试02, sex=女, birthday=null, address=bj]
关联查询

商品订单数据模型


一对一查询

查询所有订单信息,关联查询下单用户信息

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

这里有两种方式,一种是resultType,一种是resultMap

就使用第二种吧resultMap,返回pojo类,那就需要改造一下Order类,添加User对象

package cn.itcast.mybatis.pojo;

import java.util.Date;

public class Order {
	// 订单id
	private int id;
	// 用户id
	private Integer userId;
	// 订单号
	private String number;
	// 订单创建时间
	private Date createtime;
	// 备注
	private String note;

	private User user;

	//get/set方法和toString方式省略

}

UserMapper.xml

<!-- resultMap最终要映射到pojo上,type是指定到那个pojo上的 -->
	<!-- 因为sqlMapConfig配置mapper扫描pojo  配置typeAliases别名 不区分大小写 -->
	<resultMap type="order" id="orderResultMap">
		<!-- column:主键在数据库列名 property为pojo属性名 -->
		<id column="id" property="id"/>
		<result column="user_id" property="userId"/>
		<result column="number" property="number"/>
		<result column="createtime" property="createtime"/>
		<result column="note" property="note"/>
		<!-- 配置一对一属性
			property:是order里user属性
			javaType:属性类型
		 -->
		<association property="user" javaType="user">
			<!-- id:声明主键    user_id:表示关联查询对象的唯一标识	 -->
			<id column="user_id" property="id"/>
			<result property="username" column="username"/>
			<result property="address" column="address"/>
		</association>
	</resultMap>	
	
	<select id="queryOrderUserResultMap" resultMap="orderResultMap">
		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>

测试

@Test
	public void queryOrderUserResultMapTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		OrderMapper orderMapper = openSession.getMapper(OrderMapper.class);	
		List<Order> list = orderMapper.queryOrderUserResultMap();
		for (Order order : list) {
			System.out.println(order);
		}
	}

结果:

log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Order [id=1, userId=28, number=10000001, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
Order [id=2, userId=28, number=10000002, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
Order [id=3, userId=29, number=10000003, createtime=Tue Mar 27 00:00:00 CST 2018, note=null]
一对多查询

查询所有用户信息及用户关联的订单信息,用户信息和订单信息为一对多关系。

改造User类

package cn.itcast.mybatis.pojo;

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

public class User {
	private int id;
	private String username;
	private String sex;
	private Date birthday;
	private String address;
	//一个用户可以有多个订单
	private List<Order> orders;
}
<!-- 配置用户订单的ResultMap -->
	<resultMap type="user" id="userOrderResultMap">
		<!-- 配置id主键 -->
		<id column="id" property="id" />

		<!-- 配置result -->
		<result column="username" property="username" />
		<result column="birthday" property="birthday" />
		<result column="sex" property="sex" />
		<result column="address" property="address" />

		<!-- collection:配置一对多的映射关系 -->
		<!-- property:映射的属性名 -->
		<!-- javaType:属性类型 -->
		<!-- ofType:集合里面元素的类型 -->
		<collection property="orders" javaType="List" ofType="Order">
			<!-- 配置id主键 -->
			<id column="oid" property="id" />

			<!-- 配置其他属性 -->
			<result column="number" property="number" />
			<result column="createtime" property="createtime" />
			<result column="note" property="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>

测试:

@Test
	public void queryUserOrderTest(){
		SqlSession openSession = this.sqlSessionFactory.openSession();
		UserMapper userMapper = openSession.getMapper(UserMapper.class);	
		List<User> userOrder = userMapper.queryUserOrder();
		for (User user : userOrder) {
			System.out.println(user);
		}
	}

测试结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值