mybatis-动态代理式模式详细

核心配置文件:SqlMapConfig.xml

该配置文件主要注意:

  • 加载参数配置
  • typeAliases 别名的配置 (包扫描方式)
  • mappers 加载映射文件配置(映射文件包扫描,推荐方式:)
<?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>

	<!-- 先加载内部标签,再加载外部文件,名称一致时,会替换内容 -->
	<properties resource="jdbc.properties">
		<property name="jdbc.username" value="root1"/>
		<property name="jdbc.password" value="root"/>
	</properties>
	
	<typeAliases>
		<!-- 单个别名定义,别名的使用,不区分大小写 -->
		<!-- <typeAlias type="com.User" alias="user"/> -->
		<!-- 别名包扫描器:别名是类的全称,不区分大小写,推荐方式 -->
		<package name="com.bo"/>
	</typeAliases>
	
	<!-- 和spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 加载映射文件 -->
	<mappers>
		<!-- 映射文件包扫描,推荐方式:
			 1、接口文件必须与映射文件同一目录下
			 2、接口文件名称必须与映射文件的名称一致 -->
		<package name="com.mapper"/>
	</mappers>
</configuration>

映射文件

下边以UserMapper.xml 示例
需要注意的点:

  • 动态代理开发规则:
  1. namespace必需是接口的全路径名
  2. 接口的方法名必需与sql id 一致
  3. 接口的入参与parameterType类型一致
  4. 接口的返回值必须与resultType类型一致
  • 多参数查询时 where 和 if 标签 的使用
  • foreach循环标签collection:要遍历的集合
    1. open: 循环开始之前输出的内容
    2. item: 设置的循环变量
    3. separator : 分隔符
    4. close : 循环结束周输出的内容
  • 使用result绑定普通字段 , 以及sql语句起别名
  • collection用于配置一对多关联
    property:User当中Order的属性
    ofType:orders的数据类型,支持别名
<?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:命名空间,用于隔离sql语句    #{}:占位符,相当于jdbc的? ${}:字符串拼接指令,如果入参为普通数据类型{}内部只写value -->
<!-- 动态代理开发规则: 1、namespace必需是接口的全路径名 2、接口的方法名必需与sql id 一致 3、接口的入参与parameterType类型一致 
	4、接口的返回值必须与resultType类型一致 -->
	<!-- 如果在SqlMapConfig.xml里边使用包扫描的方式或类加载模式加载映射文件的话, -->
<mapper namespace="com.mapper.UserMapper">

	<!-- sql片段的抽取,定义 -->
	<sql id="user_sql">
		`id`,
		`username`,
		`birthday`,
		`sex`,
		`address`
	</sql>

	<!-- id:sql id,语句的唯一标识 parameterType:入参的数据类型 resultType:返回结果的数据类型 -->
	<select id="getUserById" parameterType="int" resultType="uSEr">
		SELECT
		<!-- sql片段使用:refid引用定义好的sql片段id -->
		<include refid="user_sql" />
		FROM `user`
		WHERE id = #{id2}
	</select>

	<!-- resultType:如果返回结果为集合,只需设置为每一个的数据类型 -->
	<select id="getUserByUserName" parameterType="string"
		resultType="com.bo.User">
		SELECT
		<include refid="user_sql" />
		FROM `user`
		<!-- WHERE username LIKE #{name} -->
		WHERE username LIKE '%${value}%'
	</select>

	<!-- 插入用户 -->
	<!-- useGeneratedKeys:使用自增 keyProperty与之配套使用,这里是user的主键 -->
	<insert id="insertUser" parameterType="com.bo.User"
		useGeneratedKeys="true" keyProperty="id">
		<!-- selectKey:主键返回 keyProperty:user中的主键属性 resultType:主键数据类型 order:指定selectKey何时执行:AFTER之后 -->
		<!-- <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT 
			LAST_INSERT_ID() </selectKey> -->
		INSERT INTO `user`
		(`username`,
		`birthday`,
		`sex`,
		`address`)
		VALUES (#{username},
		#{birthday},
		#{sex},
		#{address});
	</insert>

	<!-- 删除用户 -->
	<delete id="deleteUser" parameterType="Integer" >
	    DELETE FROM `user` WHERE `id` = #{id}
	</delete>
	
	<!-- ===============================================  进阶 ======================================== -->
	<!-- 包装类 -->
	<!-- Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。 -->
	<!-- resultType:如果返回结果为集合,只需设置为每一个的数据类型 -->
	<select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
		SELECT
		<!-- sql片段使用:refid引用定义好的sql片段id -->
		<include refid="user_sql" />
		From `user`
		<!-- 注意 这里不要忘记加上user.  否则匹配不上-->
		Where id = #{user.id}
	</select>
	
	<!-- 多参数查询 : <where> <if> 的使用 -->
	<select id="getUsersByQueryVo" parameterType ="user" resultType="user">
		SELECT
		<!-- sql片段使用:refid引用定义好的sql片段id -->
		<include refid="user_sql" />
		From `user`
		<!-- WHERE username LIKE #{name} -->
		<!-- 使用where、if 标签 -->
		<!-- <where> 自动补上where关键字,同时处理多余的and,用了where标签就不能再手动加上where关键字  -->
		<where>
		<!-- 经过测试  test之内不能用ognl表达式, 否则 if 语句会失效 -->
			<if test="username != null and username != '' ">
				and username LIKE '%${username}%'
			</if>
			<if test="sex != null and sex != '' ">
				and sex = #{sex}
			</if>
		</where>
	</select>
	
	<!-- sql语句 in 的实现  : foreach循环标签 -->
	<select id="getUserByIds" parameterType="queryvo" resultType="user">
		 SELECT
		 <include refid="user_sql"/>
		 FROM `user`
		 <where>
		 	<!-- foreach循环标签collection:要遍历的集合 
		 		open: 循环开始之前输出的内容  item: 设置的循环变量
		 		separator : 分隔符
		 		close : 循环结束周输出的内容
		 	-->
		 	<!-- 目的:id IN(1,25,29,30,35) -->
		 	<foreach collection="ids" open="id IN(" item="uId" separator="," close=")">
		 		#{uId}
		 	</foreach>
		 </where>
	</select>
	
	<!-- 使用result绑定普通字段 -->
	<resultMap type="user" id="user_order_map">
		<!-- <id>用于映射主键 -->
		<id property="id" column="id"/>
		<result property="username" column="username"/>
		<result property="address" column="address"/>
		<result property="birthday" column="birthday"/>
		<result property="sex" column = "sex"/>
		<!-- collection用于配置一对多关联 
			 property:User当中Order的属性
			 ofType:orders的数据类型,支持别名
		 -->
		<collection property="orders" ofType="order">
			<!-- <id>用于映射主键 -->
			<!-- 这里column写的oid是根据sql语句中的别名写的。为何写别名? 可能和user的id冲突 -->
			<!-- 需要注意property 是指对象属性的, column是指sql查询语句的字段的,如果有别名的话需要写别名。 -->
			<id property="id" column="oid"/> 
			<result property="userId" column="id"/><!-- 注意:这里的id 是 user表里的id  property对应的是order表里的。该配置=`user_id` = u.`id` -->
			<result property="number" column="number"/>
			<result property="createtime" column="createtime"/>
			<result property="note" column="note"/>
		</collection>
	</resultMap>
	
	<select id="getUserOrderMap" resultMap="user_order_map">
			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 o.`user_id` = u.`id`
	</select>
</mapper>

实体类示例

mybatis-动态代理式模式详细

接口示例

package com.mapper;

import java.util.List;

import com.bo.QueryVo;
import com.bo.User;

/**
 * 用户信息持久化接口  动态代理 不需要实现类
 * @author Steven
 *
 */
public interface UserMapper {
   
	/**
	 * 根据用户ID查询用户信息
	 * @param id
	 * @return
	 */
	User getUserById(Integer id);
	/**
	 * 根据用户名查找用户列表
	 * @param userName
	 * @return
	 */
	List<User> getUserByUserName(String userName);
	/**
	 * 添加用户
	 * @param user
	 */
	void insertUser(User user);
	
	/**
	 * 删除用户
	 * @param id
	 */
	void deleteUser(Integer id);
	//**********************************************
	/**
	 * 包装类查询用户
	 * @param queryvo
	 * @return
	 */
	User getUserByQueryVo(QueryVo queryvo);
	
	/**
	 * 根据 用户名 和 性别查询用户
	 * @param user
	 * @return
	 */
	List<User> getUsersByQueryVo(User user);
	/**
	 * 演示-foreach标签的使用,跟据用户id列表查询用户
	 * @param vo
	 * @return
	 */
	List<User> getUserByIds(QueryVo vo);
	/**
	 * 演示一对多关联查询-ReaultMap
	 * @param user
	 * @return
	 */
	List<User> getUserOrderMap();
}

测试

package com.test;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.bo.Order;
import com.bo.QueryVo;
import com.bo.User;
import com.mapper.UserMapper;
import com.tuils.SqlSessionFactoryUtils;
public class UserMapperTest {
	@Test
	public void testGetUserById() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = userMapper.getUserById(10);	
		System.out.println(user);
		sqlSession.close();
	}
	//根据用户名查找用户
	@Test
	public void testGetUserByUserName() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		
		List<User> userList = userMapper.getUserByUserName("张");
		
		for(User user : userList) {
			System.out.println(user);
		}
		//关闭sqlSession
		sqlSession.close();
	}
	
	//根据用户名查找用户
	@Test
	public void testInsertUser() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = new User();
		user.setBirthday(new Date());
		user.setAddress("阿拉斯加");
		user.setSex("熊");
		user.setUsername("熊二");
		userMapper.insertUser(user);
		System.out.println(user+"---------");
		sqlSession.commit();
		//关闭sqlSession
		sqlSession.close();
	}
	
	//删除用户
	@Test
	public void deleteUser() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(true);
	    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
	    mapper.deleteUser(31);
	    sqlSession.close();
	}
	//====================================================2=====================================
	//简单的包装类
	@Test
	public void testQueryVoById() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		QueryVo queryvo = new QueryVo();
		User user = new User();
		user.setId(29);
		queryvo.setUser(user);
		User result_user = userMapper.getUserByQueryVo(queryvo);
		System.out.println(result_user);
		sqlSession.close();
	}
	
	// 多参数查询  根据用户名和性别查询
	// 
	@Test
	public void testQueryPojo() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		//QueryVo queryvo = new QueryVo();
		User user = new User();
		user.setUsername("熊二");
		user.setSex("熊");
	//	queryvo.setUser(user);
		List<User> userList = userMapper.getUsersByQueryVo(user);
		 for(User user2 : userList) {
			 System.out.println(user2);
		 }
		sqlSession.close();
	}
	
	//简单的包装类  ids ***** 参数为集合
	@Test
	public void testQueryVoByIds() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		QueryVo queryvo = new QueryVo();
		//构建id列表
		queryvo.setIds(Arrays.asList(1,10,16,24));
		List<User> userList = userMapper.getUserByIds(queryvo);
		 for(User user2 : userList) {
			 System.out.println(user2);
		 }
		sqlSession.close();
	}
	// 一对多
	@Test
	public void getUserOrderMap() {
		SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		//获取接口的代理人实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		List<User> list = userMapper.getUserOrderMap();
		for (User user2 : list) {
			System.out.println(user2);
			for (Order order : user2.getOrders()) {
				if(order.getId() != null){
					System.out.println("      此用户下的订单有:" + order);
				}
			}
		}
		sqlSession.close();
	}
}

附:项目文件结构

mybatis-动态代理式模式详细