「Mybatis系列」高级应用

本系列文章Github 后端进阶指南 已收录,此项目正在完善中,欢迎star。

1. Mybatis的开发方式

此处使用的是JDK的动态代理方式,延迟加载使用的cglib动态代理方式

1.1 代理理解

代理分为静态代理和动态代理。此处先不说静态代理,因为Mybatis中使用的代理方式是动态代理。

动态代理分为两种方式:

  • 基于JDK的动态代理–针对有接口的类进行动态代理
  • 基于CGLIB的动态代理–通过子类继承父类的方式去进行代理。

1.2 XML方式

  • 开发方式

    只需要开发Mapper接口(dao接口)和Mapper映射文件,不需要编写实现类。

  • 开发规范

    Mapper接口开发方式需要遵循以下规范:

    1、 Mapper接口的类路径与Mapper.xml文件中的namespace相同。

    2、 Mapper接口方法名称和Mapper.xml中定义的每个statement的id相同。

    3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。

    4、 Mapper接口方法的返回值类型和mapper.xml中定义的每个sql的resultType的类型相同。

  • mapper映射文件

<?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.kkb.mybatis.mapper.UserMapper">
<!-- 根据id获取用户信息 -->
	<select id="findUserById" parameterType="int" resultType="com.kkb.mybatis.po.User">
		select * from user where id = #{id}
	</select>
</mapper>
  • mapper接口
/**
 * 用户管理mapper
 */
public interface UserMapper {
	//根据用户id查询用户信息
	public User findUserById(int id) throws Exception;
}
  • 全局配置文件中加载映射文件
<!-- 加载映射文件 -->
  <mappers>
    <mapper resource="mapper/UserMapper.xml"/>
  </mappers>

  • 测试代码
public class UserMapperTest{

	private SqlSessionFactory sqlSessionFactory;

@Before
	public void setUp() throws Exception {
		//mybatis配置文件
		String resource = "SqlMapConfig.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		//使用SqlSessionFactoryBuilder创建sessionFactory
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}
	@Test
	public void testFindUserById() throws Exception {
		//获取session
		SqlSession session = sqlSessionFactory.openSession();
		//获取mapper接口的代理对象
		UserMapper userMapper = session.getMapper(UserMapper.class);
		//调用代理对象方法
		User user = userMapper.findUserById(1);
		System.out.println(user);
		//关闭session
		session.close();
		
	}
}

1.3 注解方式

  • 开发方式

    只需要编写mapper接口文件接口。

  • mapper接口
public interface AnnotationUserMapper {
	// 查询
	@Select("SELECT * FROM user WHERE id = #{id}")
	public User findUserById(int id);

	// 模糊查询用户列表
	@Select("SELECT * FROM user WHERE username LIKE '%${value}%'")
	public List<User> findUserList(String username);

	// 添加并实现主键返回
	@Insert("INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})")
	@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", resultType = int.class, before = false)
	public void insertUser(User user);

}
  • 测试代码
public class AnnotationUserMapperTest {

	private SqlSessionFactory sqlSessionFactory;

	/**
	 * @Before注解的方法会在@Test注解的方法之前执行
	 * 
	 * @throws Exception
	 */
	@Before
	public void init() throws Exception {
		// 指定全局配置文件路径
		String resource = "SqlMapConfig.xml";
		// 加载资源文件(全局配置文件和映射文件)
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 还有构建者模式,去创建SqlSessionFactory对象
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}

	@Test
	public void testFindUserById() {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

		User user = userMapper.findUserById(1);
		System.out.println(user);
	}

	@Test
	public void testFindUserList() {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

		List<User> list = userMapper.findUserList("老郭");
		System.out.println(list);
	}

	@Test
	public void testInsertUser() {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

		User user = new User();
		user.setUsername("开课吧-2");
		user.setSex("1");
		user.setAddress("致真大厦");
		userMapper.insertUser(user);
		System.out.println(user.getId());
	}

}

2. 全局配置文件

2.1 配置内容

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)--Java类型--JDBC类型--->数据库类型转换

objectFactory(对象工厂)

plugins(插件)--可以在Mybatis执行SQL语句的流程中,横叉一脚去实现一些功能增强,比如PageHelper分页插件,就是第三方实现的一个插件

environments(环境集合属性对象)

environment(环境子属性对象)
       transactionManager(事务管理)
       dataSource(数据源)
mappers(映射器)

2.2 properties标签

SqlMapConfig.xml可以引用java属性文件中的配置信息。

1、在classpath下定义db.properties文件,

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

2、在SqlMapConfig.xml文件中,引用db.properties中的属性,具体如下:

   <properties resource="db.properties"/>
	<environments default="development">
		<environment id="development">
			<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>

properties标签除了可以使用resource属性,引用properties文件中的属性。还可以在properties标签内定义property子标签来定义属性和属性值,具体如下:

<properties>
	<property name="driver" value="com.mysql.jdbc.Driver"/>
</properties>

注意: MyBatis 将按照下面的顺序来加载属性

  • 读取properties 元素体内定义的属性。
  • 读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

2.3 typeAlias标签

别名的作用:就是为了简化映射文件中parameterType和ResultType中的POJO类型名称编写。

2.3.1 默认支持别名
别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
mapMap
2.3.2 自定义别名

在SqlMapConfig.xml中进行如下配置:

<typeAliases>
	<!-- 单个别名定义 -->
	<typeAlias alias="user" type="com.kkb.mybatis.po.User"/>
	<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
	<package name="com.kkb.mybatis.po"/>
</typeAliases>

2.4 mappers标签

<mapper resource=""/>

使用相对于类路径的资源

如:

<mapper resource="sqlmap/User.xml" />
<mapper url="">

使用绝对路径加载资源

如:

<mapper url="file://d:/sqlmap/User.xml" />
<mapper class=""/>

使用mapper接口类路径,加载映射文件。

如:

<mapper class="com.kkb.mybatis.mapper.UserMapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

<package name=""/>

注册指定包下的所有mapper接口,来加载映射文件。

如:

<package name="com.kkb.mybatis.mapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

3. 输入映射和输出映射

3.1 parameterType(输入类型)

parameterType属性可以映射的输入参数Java类型有:简单类型、POJO类型、Map类型、List类型(数组)

  • Map类型和POJO类型的用法类似,这里只讲POJO类型的相关配置。

  • List类型在动态SQL部分进行讲解。

传递简单类型

参考《Mybatis基础》(在我的主页内查找)中用户查询的案例。

传递pojo对象

参考《Mybatis基础》(在我的主页内查找)中的添加用户的案例。

传递pojo包装对象

包装对象:pojo类中嵌套pojo。

需求

通过包装POJO传递参数,完成用户查询。

QueryVO

定义包装对象QueryVO

public class QueryVO {
     private User user;
}
SQL语句
SELECT * FROM user where username like '%小明%'
Mapper文件
	<!-- 使用包装类型查询用户 
		使用ognl从对象中取属性值,如果是包装对象可以使用.操作符来取内容部的属性
	-->
	<select id="findUserList" parameterType="queryVo" resultType="user">
		SELECT * FROM user where username like '%${user.username}%'
	</select>

Mapper接口
/**
 * 用户管理mapper
 */
public interface UserMapper {
 	//综合查询用户列表
	public List<User> findUserList(QueryVo queryVo)throws Exception; 
}
测试方法

在UserMapperTest测试类中,添加以下测试代码:

@Test
	public void testFindUserList() throws Exception {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		//获得mapper的代理对象
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		//创建QueryVo对象
		QueryVo queryVo = new QueryVo();
		//创建user对象
		User user = new User();
		user.setUsername("小明");

		queryVo.setUser(user);
		//根据queryvo查询用户
		List<User> list = userMapper.findUserList(queryVo);
		System.out.println(list);
		sqlSession.close();
	}

3.2 resultType(输出类型)

resultType属性可以映射的java类型有:简单类型、POJO类型、Map类型

不过Map类型和POJO类型的使用情况类似,所以只需讲解POJO类型即可。

3.2.1 使用要求

使用resultType进行输出映射时,要求sql语句中查询的列名和要映射的pojo的属性名一致。

3.2.2 映射简单类型
案例需求

查询用户记录总数。

Mapper映射文件
<!-- 获取用户列表总数 -->
	<select id="findUserCount" resultType="int">
	   select count(1) from user
	</select>
Mapper接口
	//查询用户总数
	public int  findUserCount() throws Exception; 
测试代码

在UserMapperTest测试类中,添加以下测试代码:

     @Test
	public void testFindUserCount() throws Exception {
		SqlSession sqlSession = sessionFactory.openSession();
		//获得mapper的代理对象
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		
         int count = userMapper.findUserCount(queryVo);
         System.out.println(count);

		sqlSession.close();
	}


注意:输出简单类型必须查询出来的结果集只有一列。

3.2.3 映射pojo对象

注意:不管是单个POJO还是POJO集合,在使用resultType完成映射时,用法一样。

参考《Mybatis基础》(在我的主页内查找)中根据用户ID查询用户信息和根据名称模糊查询用户列表的案例

4. resultMap

4.1 使用要求

如果sql查询列名和pojo的属性名可以不一致,通过resultMap将列名和属性名作一个对应关系,最终将查询结果映射到指定的pojo对象中。

注意:resultType底层也是通过resultMap完成映射的。

4.2 需求

将以下sql的查询结果进行映射:

SELECT id id_,username username_,birthday birthday_ FROM user
4.3 Mapper接口
// resultMap入门
public List<User> findUserListResultMap() throws Exception; 
4.4 Mapper映射文件

由于sql查询列名和User类属性名不一致,所以不能使用resultType进行结构映射。

需要定义一个resultMap将sql查询列名和User类的属性名对应起来,完成结果映射。

	<!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
	<!-- 
		type:指定查询结果要映射的pojo的类型
		id:指定resultMap的唯一标示
	 -->
	<resultMap type="user" id="userListResultMap">
		<!-- 
		id标签:映射查询结果的唯一列(主键列)
			column:查询sql的列名
			property:映射结果的属性名
		-->
		<id column="id_" property="id"/>
		<!-- result标签:映射查询结果的普通列 -->
		<result column="username_" property="username"/>
		<result column="birthday_" property="birthday"/>
	</resultMap>

	<!-- resultMap入门 -->
	<select id="findUserListResultMap" resultMap="userListResultMap">
		SELECT id id_,username username_,birthday birthday_ FROM user
	</select>


  • <id/>:表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个

    • Property:表示User类的属性。
    • Column:表示sql查询出来的字段名。
    • Column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
  • <result/>:普通结果,即pojo的属性。

本系列文章Github 后端进阶指南 已收录,此项目正在完善中,欢迎star。

公众号内文章都是博主原创,并且会一直更新。如果你想见证或和博主一起成长,欢迎关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值