Mybatis框架_day01

学习笔记,把笔记放在本地,没有电脑时就没办法了,找个博客放笔记。

1. 什么是mybatis

  • mybatis是一个持久层的框架,是Apache下的顶级项目。
  • mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
  • mybatis可以将preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象(输出映射

2. Mybatis框架

在这里插入图片描述

3. 入门程序

3.1. 需求

  • 根据用户id(主键)查询用户信息
  • 根据用户名称模糊查询用户信息
  • 添加用户
  • 删除用户
  • 更新用户

3.2. Mybatis运行环境

  1. 导入mybatis3.2.7jar核心包

  2. lib下,依赖包

  3. log4j.properties

  4. 数据库驱动包

  5. SqlMapConfig.xml

    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    	<!-- 和spring整合后environments配置将废除 -->
    	<environments default="development">
    		<environment id="development">
    			<!-- 使用jdbc事务管理 -->
    			<transactionManager type="JDBC">
    				<!-- 数据库连接池 -->
    				<dataSource type="POOLED">
    					<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
    					<property name="url" value="jdbc:sqlserver://localhost:1433;database=mybatis_day01" />
    					<property name="username" value="sa" />
    					<property name="password" value="123456" />
    				</dataSource>
    			</transactionManager>
    		</environment>
    	</environments>
    </configuration>
    

3.3. 根据用户id(主键)查询用户信息

3.3.1. 创建po类
public class User {

	//属性名和数据库表的字段对应
	private int id;
	private String username;
	private String sex;
	private Date birthday;
	private String address;
3.3.2. 映射文件
  • 映射文件名称:

    • User.xml,mapper代理开发映射文件名称加XXXMapper.xml,比如:UserMapper.xml、itemsMapper.xml
  • 在映射文件中配置sql语句

    <?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进行分类化管理,理解sql隔离
    注意:使用mapper代理方法开发,namespace有特殊重要作用
    -->
    <mapper namespace="test">
    	<!-- 在映射文件中配置很多sql语句 -->
    	<!--
    	通过select执行数据库查询
    	id:用于表示映射文件中的sql
    	将sql语句封装到mapperstatement对象中,所以将id成为statement的id
    	parameterType:指定输入参数类型,这里指定int型
    	#{}表示一个占位符
    	#{id}:其中id表示接收输入的参数,参数名称为id,如果输入参数是简单类型,#{}中的参数名可以任意,可以是value或其他名称
    	resultType:输出结果所映射的java对象类型,select执行resultType表示将单条记录所映射成的java对象
    	-->
    	<select id="findUserBuId" parameterType="int" resultType="cn.itcast.mybatis.po.User">
    		SELECT * FROM t_user WHERE id = #{id}
    	</select>
    </mapper>
    
  • 在sqlMapConfig.xml加载映射文件

     <!-- 加载映射文件 -->
     <mappers>
     	<mapper resource="sqlmap/User.xml"/>
     </mappers>
    
3.3.3. 写测试代码
	//mybatis配置文件
	String resource = "SqlMapConfig.xml";
	//得到配置文件流
	InputStream inputStream = Resources.getResourceAsStream(resource);
		
	//创建会话工厂,传入mybatis的配置文件信息
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			
	//通过会话工厂得到sqlsession
	SqlSession sqlSession = sqlSessionFactory.openSession();
			
	//通过sqlsession操作数据库
	//第一个参数:映射文件中statement的id,等于namespace+"."+statement的id
	//指定和映射文件中管所匹配的parameterType类型的参数
	//最终结果是与映射文件中所匹配的resultType类型的对象
	User user = sqlSession.selectOne("test.findUserById",1);
		
	System.out.println(user);

3.4. 根据用户名称模糊查询用户信息

3.4.1 映射文件
  • 使用User.xml

       <!-- 根据用户名称模糊查询用户信息,可返回多条
        	 resultType指定的就是将单条记录所映射成的java对象类型
        	 ${}:表示拼接sql语句,将接收到参数的内容不加任何修饰拼接在sql中
        	 使用${}拼接sql,引起sql注入
        	 ${value}:接收输入参数的内容,如果传入类型是简单类型,${}中是能使用value
        	  -->
        	 <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
        	 	SELECT * FROM t_user WHERE username LIKE '%${value}%'
        	 </select>
    
3.4.2 程序代码
List<User> list = sqlSession.selectList("test.findUserByName", "赵");

3.5. 添加用户

3.5.1 映射文件
  • 在User.xml文件中配置添加用户的Statement

    <!-- 添加用户
    	parameterType:指定输入参数类型是pojo(包括用户信息)
    	#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值 -->
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
    	INSERT INTO t_user(username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
    </insert>
    
3.5.2. 程序代码
//插入用户对象
User user = new User();
user.setUsername("王小军");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("中国");
		
sqlSession.insert("test.insertUser", user);
		
//提交事务
sqlSession.commit();
3.5.3. 自增主键的返回
  • 在MySQL中使用函数SELECT LAST_INSERT_ID();在SQLServer中可用其函数SELECT SCOPE_IDENTITY()

  • MySQL中可用

    <!-- 将插入的主键返回,返回到user对象中
    	SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用于自增主键
    	keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
    	order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说
    	resultType:指定SELECT LAST_INSERT_ID()的结果类型 -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    	SELECT LAST_INSERT_ID()
    </selectKey>
    
  • SQLServer中用

    <!-- 方法一 -->
    <!-- keyProperty 是实体里面的属性,如果传入是map就是map里的属性,
    	keyColumn是表上的主键名称 -->
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    	INSERT INTO t_user(username,birthday,sex,address)
    	VALUES (#{username},#{birthday},#{sex},#{address})
    	SELECT SCOPE_IDENTITY()
    </insert>
    <!-- 方法二 -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    	SELECT @@IDENTITY
    </selectKey>
    
3.5.4. 非自增主键的返回(使用uuid())

3.6. 删除用户

3.6.1. 映射文件
<!-- 根据id删除 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
    DELETE FROM t_user WHERE id=#{id}
 </delete>
3.6.2. 代码实现
//传入id删除用户
sqlSession.delete("test.deleteUser", 8);

3.7. 更新用户

3.7.1. 映射文件
<!-- 更新用户
   需要传入用户id
   需要传入用户更新信息
   parameterType指定user对象,包括id和更新信息,注意:id必须存在
   #{id}:从输入的user对象中获取id属性值 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
   update t_user set username=#{username},birthday=#{birthday},sex=#{sex},address={address} where id=#{id}
</update>
3.7.2. 代码实现
//更新用户对象
User user = new User();
user.setId(15);
user.setUsername("王大小");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("中国");
		
//传入id删除用户
sqlSession.update("test.updateUser", user);

3.8. 总结

3.8.1. parameterType
  • 在映射文件中通过parameterType指定输入参数的类型
3.8.2. resultType
  • 在映射文件中通过resultType指定输出结果的类型
3.8.3. #{}和${}
  • #{}表示一个占位符。
    • #{}接收输入参数,类型可以是简单类型,pojo,hashmap。如果接收的是简单类型。
    • #{}中可以写成value或其他名称。
    • #{}接收pojo对象值,通过OGNL解析对象中的属性值,通过属性.属性.属性…
  • ${}表示一个拼接符号,会引起sql注入,不建议使用
    • ${}接收输入参数,类型可以是简单类型,pojo,hashmap。如果接收的是简单类型。
    • 如果接收简单类型,只能写成vlaue。
    • ${}接收pojo对象值,通过OGNL解析对象中的属性值,通过属性.属性.属性…
3.8.4. selectOne和selectList
  • selectOne表示查询出一条记录进行映射,如果使用selectOne可以实现,使用selectList也可以实现(list中只有一个记录)
  • selectList表示查询吃一个列表(多条记录)进行映射,不可以使用selectOne实现

3.9. Mybatis和Hibernate本质区别和应用场景

3.9.1. Hibernate
  • 是一个标准的ORM框架(对象关系映射)。入门门槛高,不需要程序员写sql,sql语句自动生成。对sql语句进行优化、修改比较困难。
  • 应用场景:适用于需求变化不多的中小型项目,比如:后台管理系统,erp,orm,oa。
3.9.2. Mybatis
  • 专注是sql本身,需要程序员写sql语句,sql修改、有话比较方便。mybatis是一个不完全的ORM框架,虽然程序员自己写sql,mybatis也可以实现映射(输入映射、输出映射)。
  • 应用场景:适用于需求变化较多的项目,比如:互联网项目。

4. Mybatis开发dao的方法

4.1. sqlSession适用范围

4.1.1. SqlSessionFactoryBuilder
  • 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
  • 将SqlSessionFactoryBuilder当成工具类即可,不需要使用单例管理SqlSessionFactoryBuilder
  • 在需要创建SqlSessionFactory时,只需要new一次SqlSessionFactoryBuilder即可
4.1.2. SqlSessionFactory
  • 通过SqlSessionFactory创建Sqlsession,使用单例模式管理SQLSessionFactory(工厂一旦创建,使用一个实例)
  • 将来mybatis和spring整合之后,使用单例模式管理SQLSessionFactory
4.1.3. SqlSession
  • SqlSession是一个面向用户(程序员)的接口
  • SqlSession中提供了很多操作数据库的方法,如:selectOne(返回单个对象)、selectList(返回单个或多个对象)
  • SqlSession是线程不安全的,在SqlSession实现勒种,除了有接口中的方法(操作数据库的方法)还有数据域属性。
  • SqlSession最佳应用场合在方法体内,定义成局部变量使用。

4.2. 原始dao开发方法(程序员需要些dao接口和dao实现类)

4.2.1. 思路
  • 需要向dao实现类中注入会话工厂SqlSessionFactory,在方法体内通过工厂创建SqlSession
4.2.2. Dao接口
public interface UserDao {

	//根据id查询用户信息
	public User findUserById(int id) throws Exception;

	//添加用户信息
	public void inserUser(User user) throws Exception;

	//删除用户信息
	public void deleteUser(int id) throws Exception;
}
4.2.3. Dao实现类
public class UserDaoImpl implements UserDao{

	//需要向dao实现类中注入SqlSessionFactory
	//通过构造方法注入
	private SqlSessionFactory sqlSessionFactory = null;
	public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

	@Override
	public User findUserById(int id) throws Exception {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		User user = sqlSession.selectOne("test.findUserById",id);
		//释放资源
		sqlSession.close();
		return user;
	}

	@Override
	public void inserUser(User user) throws Exception {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		sqlSession.insert("test.insertUser", user);
		//执行事务
		sqlSession.commit();
		//释放资源
		sqlSession.close();
	}

	@Override
	public void deleteUser(int id) throws Exception {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		sqlSession.delete("test.deleteUser", id);
		//执行事务
		sqlSession.commit();
		//释放资源
		sqlSession.close();
	}

}
4.2.4. 测试代码
public class UserDaoImplTest {

	private SqlSessionFactory sqlSessionFactory;
	//此方法是在执行testFindUserById之前执行
	@Before
	public void setUp() throws Exception {
		//创建SQLSessionFactory

		//mybatis配置文件
		String resource = "SqlMapConfig.xml";
		//得到配置文件流
		InputStream inputStream = Resources.getResourceAsStream(resource);

		//创建会话工厂,传入mybatis的配置文件信息
		sqlSessionFactory = new SqlSessionFactoryBuilder()
				.build(inputStream);
	}

	@Test
	public void testFindUserById() throws Exception {
		//创建userDao对象
		UserDao userDao = new UserDaoImpl(sqlSessionFactory);
		//调用UserDao方法
		User user = userDao.findUserById(1);

		System.out.println(user);
	}

}
4.2.5. 总结原始dao开发问题
  • dao接口实现类方法中讯在大量模板方法
  • 嗲用sqlsession方法是将statement的id硬编码了
  • 调用sqlsession方法是传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误在编译阶段也不报错

4.3. mapper代理方法(程序员只需要写mapper接口(相当于dao接口))

4.3.1. 思路(mapper代理开发规范)
  • 写mapper.xml映射文件

  • 写mapper接口需遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象

  • 开发规范:

    • 在mapper.xml中mapper的namespace等于mapper.java接口的地址

      <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
      	注意:使用mapper代理方法开发,namespace有特殊重要作用 -->
      <mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
      
    • mapper.java接口中的方法名和mapper.xml中statement的id一致

    • mapper.java接口中方法的参数类型和mapper.xml中statement的parameterType指定的类型一致

    • mapper.java接口中的方法返回累心个mapper.xml中resultType指定的类型一致

      //根据id查询用户信息
      public User findUserById(int id) throws Exception;
      
  • 总结:以上开发规范主要是对下面的代码进行统一生成:

    • User user = sqlSession.selectOne("test.findUserById",id);
    • sqlSession.insert("test.insertUser", user);
    • sqlSession.delete("test.deleteUser", id);
4.3.2. mapper.java
public interface UserMapper {

	//根据id查询用户信息
	public User findUserById(int id) throws Exception;

	//根据用户名查询用户列表
	//
	public List<User> fingUserByName(String name) throws Exception;

	//插入用户
	public void insertUser(User user) throws Exception;

	//删除用户
	public void deleteUser(int id) throws Exception;

}
4.3.3. mapper.xml
4.3.4. 在SqlMapperConfig.xml中加载mapper.xml
<mapper resource="mapper/UserMapper.xml"/>
4.3.5. 测试代码
@Test
public void testFindUserById() throws Exception {
	
	SqlSession sqlSession = sqlSessionFactory.openSession();
	//创建UserMapper对象,mybatis自动生成mapper对象
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	
	User user = userMapper.findUserById(1);
	
	System.out.println(user);
}
4.3.6. 一些问题总结
4.3.6.1. 代理对象内部调用selectOne或selectList
  • 如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库.
  • 如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库.
4.3.6.2. mapper接口方法参数只能有一个
  • mapper接口方法参数只能有一个,是否不利于扩展维护。
  • 在系统框架中,dao层的代码是被业务层公用的,即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求
  • 注意:持久层中方法的参数可以用包装类型,map…,service方法中建议不要使用包装类型(不利于业务层的可扩展)

5. SqlMapConfig.xml

mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:

<properties> 用来加载属性文件
<settings> 用来设置全局参数
<typeAliases> 用来设置类型的别名
<typeHandlers> 用来设置类型处理器
<objectFactory> 用来设置对象工厂
<plugins> 用来设置插件
<environments> 用来设置mybatis的环境
<mappers> 用来配置映射文件

5.1. properties属性

5.1.1 需求
  • 将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties属性值

  • 在SqlMapConfig.xml中就不需要对数据库连接参数硬编码

  • 将数据库连接参数值配置在db.properties

    <!-- 加载属性文件 -->
    <properties resource="db.properties"></properties>
    <!-- 和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>
    
5.1.2. properties特性:
  • 注意:Mybatis将按照下面的顺序来加载属性:
    • 在properties元素体内定义的属性首先被读取
    • 然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性
    • 最后读取parameterType传递的属性,它会覆盖已读取的同名属性
5.1.3. 建议:
  • 不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中
  • 在properties文件中定义属性名要有一定的特殊性,比如:xxxx.xxxx

5.2. settings全局参数配置

  • mybatis框架在运行时可以调整一些运行参数,比如开启二级缓存,开启延迟加载

5.3. typeAliases别名定义(重点)

5.3.1. 需求
  • 在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型,需要resultType执行输出结果的映射类型
  • 如果在指定类型是输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发
5.3.2. mybatis默认支持别名

在这里插入图片描述

5.3.3. 自定义别名
5.3.3.1. 别名定义
<!-- 别名定义 -->
<typeAliases>
	<!-- 针对单个别名的定义
		type:类型的路径
		alias:别名
	 -->
	<typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
</typeAliases>
  • 引用别名

    <select id="findUserById" parameterType="int" resultType="user">
    	SELECT * FROM t_user WHERE id = #{id}
    </select>
    
5.3.3.2. 批量定义(常用)
<!-- 批量别名定义
	指定包名:mybatis自动扫描包中的po类,
	自动定义别名,别名就是类名(首字母大写或小写都可以)
 -->
<package name="cn.itcast.mybatis.po"/>

5.4. typeHandler类型处理器

  • mybatis中通过typeHandler完成jdbc类型和java类型的转换
  • 通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义

5.5. mapper映射配置

5.5.1. 通过resource方法一次加载单个映射文件
<!-- 通过resource方法一次加载一个映射文件 -->
<mapper resource="mapper/UserMapper.xml"/>
5.5.2. 通过mapper接口加载
<!-- 通过mapper接口加载映射文件
遵循一些规范:需要将mapper接口的类名和mapper.xml映射文件名称保持一致,且在一个目录中
上边规范前提是:使用的是mapper代理的方法
 -->
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
  • 按照上面的规范,需将mapper.java和mapper.xml放在同一个文件中
5.5.3. 批量加载多个mapper(推荐使用)
<!-- 批量加载mapper
mapper接口的报名,mybatis在自动扫描包下边所有mapper接口进行加载
遵循一些规范:需要将mapper接口的类名和mapper.xml映射文件名称保持一致,且在一个目录中
上边规范前提是:使用的是mapper代理的方法
 -->
<package name="cn.itcast.mybatis.mapper"/>

6. 输入映射

  • 通过parameterType指定输入参数类型,可以是简单类型,HashMap,pojo的包装类型

6.1. 传递pojo的包装对象

6.1.1 需求
  • 完成用户信息的综合查询,需要传入很多查询条件(可能包括童虎信息、其他信息,比如商品、订单的)
6.1.2. pojo包装类型
  • 针对上边需求,建议使用自定义的包装类型的pojo

  • 在包装类型的pojo中将复杂的查询条件包装进去

     public class UserQueryVo {
     
     		//在这里包装所需要的查询条件
    
     		//用户查询条件
     		private UserCustom userCustom;
     	
     		public UserCustom getUserCustom() {
     			return userCustom;
     		}
     	
     		public void setUserCustom(UserCustom userCustom) {
     			this.userCustom = userCustom;
     		}
     		
     		//可以包装其他的查询条件,比如订单,商品
     		//...
    
6.1.3. mapper.xml
  • 在UserMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂查询)。

    <!-- 用户信息综合查询
    	#{userCustom.sex}:取出pojo包装对象中性别值
    	${userCusotm.username}:取出pojo包装对象中用户姓名 -->
    <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="cn.itcast.mybatis.po.UserCustom">
    	SELECT *
    	FROM t_user where user.sex=#{userCustom.sex} and user.username like '%${userCusotm.username}%'
    </select>
    
6.1.4. mapper.java
//用户信息综合查询
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
6.1.5. 测试代码
public void testFindUserList() throws Exception {

	SqlSession sqlSession = sqlSessionFactory.openSession();
	//创建UserMapper对象,mybatis自动生成mapper对象
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	
	//创建包装对象,设置查询条件
	UserQueryVo userQueryVo = new UserQueryVo();
	UserCustom userCustom = new UserCustom();
	userCustom.setSex("男");
	userCustom.setUsername("赵");
	userQueryVo.setUserCustom(userCustom);
	//调用userMapper的方法
	List<UserCustom> list = userMapper.findUserList(userQueryVo);
	
	System.out.println(list);
}

7. 输出映射

7.1. resultType

  • 使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功
  • 如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象
  • 只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象
7.1.1. 输出简单类型
7.1.1.1. 需求
  • 用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页
7.1.1.2. mapper.xml
<!-- 用户信息综合查询总数
parameterType:指定输入类型和发ingUserList一样
 -->
<select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="int">
	SELECT COUNT(*) FROM t_user where sex=#{userCustom.sex} and username like '%${userCustom.username}%'
</select>
7.1.1.3. mapper.java
//用户信息综合查询总数
public int findUserCount(UserQueryVo userQueryVo) throws Exception;
7.1.1.4. 测试代码
public void testFindUserCount() throws Exception {

	SqlSession sqlSession = sqlSessionFactory.openSession();
	//创建UserMapper对象,mybatis自动生成mapper对象
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	
	//创建包装对象,设置查询条件
	UserQueryVo userQueryVo = new UserQueryVo();
	UserCustom userCustom = new UserCustom();
	userCustom.setSex("男");
	userCustom.setUsername("赵");
	userQueryVo.setUserCustom(userCustom);
	//调用userMapper的方法
	int count = userMapper.findUserCount(userQueryVo);
	
	System.out.println(count);
}
7.1.1.5. 小结
  • 查询出来的结果集是一行且一列,可以使用简单类型进行输出映射
7.1.2. 输出pojo对象和pojo对象列表
  • 不管输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的
  • 在mapper.java指定的方法返回值类型不一样:
    • 输出单个pojo对象,方法返回值是单个对象类型
    • 输出pojo对象列表,方法返回值是List
  • 生成的动态代理对象中是根据mapper方法的返回值类型确定调用selectOne还是selectList

7.2. resultMap

  • mybatis中可以使用resultMap完成高级输出结果映射
7.2.1. resultMap使用方法
  • 如果查询出来的列名和pojo属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做映射关系
  • 第一步 定义resultMap
  • 第二步 使用resultMap作为statement的输出映射类型
7.2.2 需求:将下边的sql使用User完成映射
SELECT id id_,username username_ FROM t_user where id=#{value}
  • User类中属性名和上边查询列名不一致
7.2.2.1. 定义resultMap
<!-- 定义resultMap
将SELECT id id_,username username_ FROM t_user和User类中的属性做一个映射关系
type:resultMap最终所映射的java对象类型,可以使用别名
id:对resultMap的唯一标识
 -->
 <resultMap type="user" id="userResultMap">
	<!-- id标识查询结果集中唯一标识
	 column:查询出来的列名
	 property:type指定的pojo类型中的属性名
	 最终resultMap对column和property做一个映射关系(对应关系)
	  -->
	 <id column="id_" property="id"/>
	 <!-- 
	 result对普通列的定义
	  -->
	  <result column="username_" property="username"/>
 </resultMap>
7.2.2.2. 使用resultMap作为statement的输出映射类型
<!-- 使用resultMap进行输出映射
resultMap:指定定义的resultMap的id,如果这个resultMap在其他的mapper文件中,前边应加namespace
 -->
<select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="userResultMap">
	SELECT id id_,username username_ FROM t_user where id=#{value}
</select>
7.2.2.3. mapper.java
//根据用户名查询用户列表
public List<User> fingUserByName(String name) throws Exception;
7.2.2.4. 测试
public void testFindUserByIdResultMap() throws Exception {

	SqlSession sqlSession = sqlSessionFactory.openSession();
	//创建UserMapper对象,mybatis自动生成mapper对象
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	
	//调用userMapper的方法
	User user = userMapper.findUserByIdResultMap(1);	
	
	System.out.println(user);
}

7.3. 小结

  • 使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功
  • 如果查询出来的列名和pojo属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做映射关系

8. 动态sql

8.1. 什么是动态sql

  • mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装

8.2. 需求

  • 用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql
  • 对查询条件进行判断,如果输入参数不为空才进行查询条件拼接。

8.3. mapper.xml

<select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" 
  resultType="cn.itcast.mybatis.po.UserCustom">
	SELECT username,address,birthday FROM t_user
	<!-- where可以自动去掉条件中第一个and -->
	<where>
		<if test="userCustom!=null">
			<if test="userCustom.sex!=null and userCustom.sex!=''">
				and sex=#{userCustom.sex}
			</if>
			<if test="userCustom.username!=null and userCustom.username!=''">
				and username like '%${userCustom.username}%'
			</if>
		</if>
	</where>
</select>

8.4. 测试代码

//创建包装对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
//由于使用动态sql,不设置值,条件不会拼接在sql中
userCustom.setSex("男");
//userCustom.setUsername("赵");
userQueryVo.setUserCustom(userCustom);
//调用userMapper的方法
List<UserCustom> list = userMapper.findUserList(null);

8.5. sql片段

8.5.1. 需求
  • 将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其他statement中就可以引用sql片段
8.5.2. 定义sql片段
<!-- 定义sql片段
id:sql片段唯一标识
经验:是基于单标定义sql片段,这样这个sql片段可重用性才高
在sql片段中不要包含where
-->
<sql id="query_user_where">
 	<if test="userCustom!=null">
		<if test="userCustom.sex!=null and userCustom.sex!=''">
			and sex=#{userCustom.sex}
		</if>
		<if test="userCustom.username!=null and userCustom.username!=''">
			and username like '%${userCustom.username}%'
		</if>
	</if>
</sql>
8.5.3. 引用sql片段
<select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" 
  resultType="cn.itcast.mybatis.po.UserCustom">
	SELECT username,address,birthday FROM t_user
	<!-- where可以自动去掉条件中第一个and -->
	<where>
		<!-- 引用sql片段的id,如果refid引用的片段不在本mapper中,需要加namespace -->
		<include refid="query_user_where"></include>
		<!-- 这里还可以引用其他的sql片段 -->
	</where>
</select>

8.6. foreach

  • 向sql传递数组或list,mybatis使用foreach解析
8.6.1. 需求
  • 在用户查询列表和查询总数的statement中,增加多个id的输入查询
  • sql语句如下:SELECT * FROM t_user WHERE id=1 or id=3 or id=4
8.6.2. 在输入参数类型中添加listids传入多个id
//传入多个id
private List<Integer> ids;
8.6.3. 修改mapper.xml
  • 在查询条件中,查询条件定义成了sql片段,需要修改sql片段

    <if test="ids!=null">
    	<!-- 使用foreach遍历传入ids
    		collection:指定输入对象中集合属性
    		item:每次遍历生成的变量名
    		open:开始便利是要拼接的串
    		close:结束遍历是拼接的串
    		separator:每遍历的两个对象中间需要拼接的串 -->
    	<!-- 实现下边的sql拼接
    		AND (id=1 OR id=3 OR id=4) -->
    	<foreach collection="ids" item="item_id" open="AND (" close=")" separator="OR">
    		<!-- 每个遍历需要拼接的串 -->
    		id=#{item_id}
    	</foreach>
    </if>
    
8.6.4. 测试代码
//传入多个id
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(3);
ids.add(4);
userQueryVo.setIds(ids);
userQueryVo.setUserCustom(userCustom);
//调用userMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值