//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>
MyBatis封装resultSet结果集时, 使用反射机制, 因此, 必须保证resultSet结果集中的属性名称与实体的名称保持一致, 因此使用 resultType 遵循以下规则:
使用类型别名后, 在parameterType, resultType中就不用写很长的类路径, 直接简写
例如: 以前 => resultType=“com.regotto.domain.User” 后来 => resultType=“user”
<typeAliases>
<!--对单个实体进行-->
<typeAlias alias="user" type="com.regotto.domain.User">
<!--扫描当前包下的类, 自动别名设定为类名(首字母大小写都行)-->
<package name="com.regotto.domain">
</typeAliases>
使用Mapper.xml (最常用)
使用注解
mapper接口与Mapper.xml文件在同一个目录中, 且文件名相同
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, 使用完毕后, 再归还连接池.
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进行手动提交.
对paramType中的参数进行判断, 条件成立, 则拼装Sql, 不成立, 不拼装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>
<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>
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:代表分隔符
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属性的对应关系
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标签
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
将多对多的关系拆分为两个一对多的关系处理
一定程度上提高查询性能, 但是造成的问题是: 当存在大量查询需要立即获得数据, 导致用户体验下降.
在SqlMapperConfig.xml配置文件中开启延迟加载:
AccountUserMapper.xml文件内容
association属性:
select: 填写我们要调用的 select 映射的 id
column : 填写我们要传递给 select 映射的参数
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是指定集合泛型.
在映射文件中设定查询结果的缓存有效:
useCache: 设定缓存是否有效
执行查询操作之后, 结果放入一级缓存中, 下次查询, 数据还是存缓存中获取.
1.在SlqMapperConfig.xml中开启二级缓存
MyBatis默认开启二级缓存
2.在select标签上配置useCache标签值
注: 使用缓存存储对象, 实体必须实现 Serializable接口
MyBatis注解开发不具有灵活性, 不使用