MyBatis动态SQL_多表查询_延迟加载_缓存

POJO包装传递对象

//POJO实体
public class QueryConditionObject {
	private User user;
	//user get,set方法
}

//Dao 接口
public interface UserMapper{
	List<User> findByCondition(QueryConditionObject qco);
}

//UserMapper.xml中的select标签
<select id="findByCondition" resultType="com.regotto.domain.User"
 parameterType="com.itheima.domain.QueryVo">
 	<!--此处使用OGNL表达式, 传递select查询的条件-->
	select * from user where username like #{user.username};
</select>

resultType or resultMap配置结果参数

MyBatis封装resultSet结果集时, 使用反射机制, 因此, 必须保证resultSet结果集中的属性名称与实体的名称保持一致, 因此使用 resultType 遵循以下规则:

  1. 数据库的列名与实体属性名保持一致(在Windows下MySQL不区分大小写, 在Linux下MySQL区分大小写, 一定要注意保持包括大小写也一致)
  2. 若数据库列名与实体属性名不一致, 使用select name as userName…, 来保持resultSet结果集属性的值与实体中的属性值一样, 保证反射属性封装成功.
  3. 使用resultMap定义表列名与实体属性的对应关系.

typeAliases(类型别名)

使用类型别名后, 在parameterType, resultType中就不用写很长的类路径, 直接简写
例如: 以前 => resultType=“com.regotto.domain.User” 后来 => resultType=“user”

<typeAliases>
	<!--对单个实体进行-->
	<typeAlias alias="user" type="com.regotto.domain.User">
	<!--扫描当前包下的类, 自动别名设定为类名(首字母大小写都行)-->
	<package name="com.regotto.domain">
</typeAliases>

mappers映射器(指定Mapper.xml或者注解修饰的类)

使用Mapper.xml (最常用)

使用注解

mapper接口与Mapper.xml文件在同一个目录中, 且文件名相同

MyBatis数据源配置

MyBatis数据源种类: UNPOOLED(不使用连接池), POOLED(使用连接池), JNDI(从JNDI上查找DataSource)
使用连接池, 提高数据库操作性能, 通常MyBatis使用的数据源为POOLED

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

MyBatis使用工厂模式创建DataSource, 源码如下:

public interface DataSourceFactory {
    void setProperties(Properties var1);
    DataSource getDataSource();
}

import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
//UnpooledDataSourceFactory implements DataSourceFactory
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
    public PooledDataSourceFactory() {
        this.dataSource = new PooledDataSource();
    }
}

根据源码PooledDataSource中popConnection(String username, String password)方法可得出, 当执行Sql语句的时候, 才会从连接池中获得一个Connection, 使用完毕后, 再归还连接池.

MyBatis事务控制

JDBC事务提交: connection.setAutoCommit(boolean b).
MyBatis中事务提交源码:

	//SqlSessionFactory.class代码如下:
    public SqlSession openSession() {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), 
        										(TransactionIsolationLevel)null, 
        										false);
    }
    public SqlSession openSession(boolean autoCommit) {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(),
        									 (TransactionIsolationLevel)null,
        									  autoCommit);
    }
    private SqlSession openSessionFromDataSource(ExecutorType execType, 
    											TransactionIsolationLevel level, 
    											boolean autoCommit)

可使用SqlSessionFactory.openSession(true)设置自动提交. 或者使用session.commit进行手动提交.

动态SQL

对paramType中的参数进行判断, 条件成立, 则拼装Sql, 不成立, 不拼装Sql

  • if标签(条件判断, where 1=1用于if条件不成立, 导致sql执行错误)
<select id="findByUser" resultType="user" parameterType="user">
	select * from user where 1=1
		<if test="username!=null and username != '' ">
			and username like #{username}
		</if> 
		<if test="address != null">
			and address like #{address}
		</if>
</select>
  • where标签(简化where 1=1的写法)
<select id="findByUser" resultType="user" parameterType="user"> 
	select * from user
	<where> 
		<if test="username!=null and username != '' ">
			and username like #{username}
		</if> 
		<if test="address != null">
			and address like #{address}
		</if>	
	</where>
</select>
  • foreach标签(等价于for循环, 重复执行Sql)
class Query{
	private List<Integer> ids;
	//ids get set方法...
}
<!-- 查询所有用户在 id 的集合之中 --> 
<select id="findInIds" resultType="user" parameterType="com.regotto.Query">
<!-- select * from user where id in (1,2,3,4,5); -->
	select * from user
		<where> 
			<if test="ids != null and ids.size() > 0"> 
				<foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
					#{uid}
				</foreach>
			</if>
		</where>
</select>

SQL 语句:select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:
	collection:代表要遍历的集合元素,注意编写时不要写#{}
	open:代表语句的开始部分
	close:代表结束部分
	item:代表遍历集合的每个元素,生成的变量名
	sperator:代表分隔符

MyBatis多表查询

  • 一对一(多对一)
    User <=> Account
1. 编写sql语句: select * from user, account where user.id = account.id;
2. 定义实体(可以使用int, String等基本属性定义, 定义的实体内容决定了Mapper.xml中select标签的编写方式)
	class AccountUser{
		private User user;
		private String id;
		private String name;
		//......
		//get, set方法
	}
3. 定义dao接口
	interface AccountUserMapper{
		AccountUser findAccountUser();
	}
4. 定义AccountUserMapper.xml文件
	resultMap建立查询结果与AccountUser属性的对应关系
	 
		
		
		
		 
		 
			
			
			
			
			
		
	 
	
  • 一对多
    User <=> 多个Account
1. 编写sql: select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid
2. 定义实体
	class User{
		private String id;
		private String name;
		private List accounts;
		//get, set方法
	}
3. 定义dao接口方法: List findAll();
4. UserMapper.xml
 
	 
	
	
	
	
	 
	 
		
		
		
	

 

相比于一对一, 若实体属性是集合等结构, 则使用collection标签

  • 多对多
    多个Role <=> 多个User, 中间表USER_ROLE
1.编写sql:
	 SELECT r.*,u.id uid, u.username username FROM ROLE r
		INNER JOIN USER_ROLE ur	ON ( r.id = ur.rid)	
		INNER JOIN USER u ON (ur.uid = u.id);
2.编写实体:
	class Role {
		private id;
		private name;
		List users;
		//get set方法
	}
3.dao接口:
	List findAll();
4.编写Mapper.xml
 
 
 	
 	
 	
 	
 		
 		
 		
 		
 		
 	
 
 
 
		select * from account
	
association属性:
select: 填写我们要调用的 select 映射的 id 
column : 填写我们要传递给 select 映射的参数
  • collection实现延迟加载
    user <=> 多个account
AccountUserMapper.xml:
 
	 
	
	
	
	 
	


 

标签:主要用于加载关联的集合对象
	select 属性:用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 id
	column 属性:用于指定 select 属性的 sql 语句的参数来源,上面的参数来自于 user 的 id 列,所以就写成 id 这一个字段名

**结论: **使用association或者collection进行延迟加载, 需要指定select, column, association与collection的区别: association使用property, javaType; collection使用property, ofType; property都是指定实体中属性的名称, javaType, ofType是指定集合泛型.

MyBatis缓存

一级缓存(SqlSession级别, Session存在缓存就存在)

在映射文件中设定查询结果的缓存有效:

 

 useCache: 设定缓存是否有效

执行查询操作之后, 结果放入一级缓存中, 下次查询, 数据还是存缓存中获取.

二级缓存(Mapper映射级别, 多个Session共用一个缓存)

1.在SlqMapperConfig.xml中开启二级缓存

MyBatis默认开启二级缓存

	 
	

2.在select标签上配置useCache标签值
注: 使用缓存存储对象, 实体必须实现 Serializable接口

MyBatis注解开发不具有灵活性, 不使用

你可能感兴趣的:(Mybatis)