MyBatis & MyBatis plus
MyBatis
配置文件:放在类路径下
<?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?,settings?,typeAliases?,
typeHandlers?,objectFactory?,objectWrapperFactory?,
reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?)
-->
<!-- 引入properties文件, 使用${}访问 -->
<properties resource="jdbc.properties"/>
<!---->
<!-- 类型别名-->
<typeAliases>
<!-- 为某个具体的类型设置别名
在MyBatis的范围内就可以使用别名表示一个具体的类型
type:设置需要起别名的类型
alias:设置某个类型的别名
不设置alias时, 别名默认是类名,且不区分大小写
-->
<!-- <typeAlias type="com.lang.mybatis.pojo.User" alias="User"/>-->
<!-- 以包的方式设置别名
此时这个包下的类,都全部拥有默认的别名
即类名,且不区分大小写
-->
<package name="com.lang.mybatis.pojo"/>
</typeAliases>
<!-- 配置连接数据库的环境
属性default:设置默认使用的环境的id
-->
<environments default="development">
<!--
environment:设置一个具体的连接数据库的环境
属性:
1).设置环境的唯一标识, 不能重复
-->
<environment id="development">
<!-- 事务管理
属性
type:JDBC和MANAGED
JDBC:表示使用JDBC中的原生的事务管理方式
MANAGED:被管理,例如Spring
-->
<transactionManager type="JDBC"/>
<!-- 数据源
属性
type:设置数据源的类型
1)POOLED:使用数据库连接池
2)UNPOOLED:不使用数据库连接池
3)JNDI:表示上下文中的数据源
-->
<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>
<!-- 引入mybatis的映射文件-->
<mappers>
<!-- 映射文件-->
<!-- <mapper resource="mappers/UserMapper.xml"/>-->
<!-- 通过包引入mapper文件
两个必须
1).映射文件的包和mapper接口的包一样,
2).映射文件的名字和mapper接口的名字一样,
-->
<package name="com.lang.mybatis.mapper"/>
</mappers>
</configuration>
读取mybatis-config.xml文件,获取SqlSession
public class SqlSessionUtil {
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
try {
//获取核心配置文件的输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession
//true可以自动提交
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
获取参数时#{param}和${param}有什么区别
-
#{param}属于占位符,会自动添加引号
-
${param}是字符串形式,有
SQL注入问题
<select id="getUserByUsername" resultType="User">
select * from t_user where username=#{username};
select * from t_user where username='${username}'
</select>
如果有两个及以上的参数,用@Param注解,或者直接可以用实体类接收
resultMap与多对一对映关系
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResult">
select *
from t_emp left join t_dept
on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = #{empId}
</select>
<resultMap id="empAndDeptResult" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="emp_age" property="empAge"/>
<result column="emp_gender" property="empGender"/>
<!-- 处理实体类类型的属性,
property 设置处理映射关系的属性名
javaType 设置处理属性的类型
-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</association>
</resultMap>
resultMap与一对多对映关系
<!-- Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);
处理一对多
-->
<select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.dept_id = t_emp.dept_id where t_dept.dept_id = #{deptId}
</select>
<resultMap id="getDeptAndEmpResultMap" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<!-- 处理一对多的映射关系
property 处理的属性名字
ofType 集合中处理的属性的类型
-->
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="emp_age" property="empAge"/>
<result column="emp_gender" property="empGender"/>
</collection>
</resultMap>
MyBatis的一级缓存(default)
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:
- 不同的
SqlSession对应不同的一级缓存 - 同一个
SqlSession但是查询条件不同 - 同一个
SqlSession两次查询期间执行了任何一次增删改操作 - 同一个
SqlSession两次查询期间手动清空了缓存(sqlSession.clearCache())
MyBatis的二级缓存(比一级缓存的范围大)
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取。
二级缓存开启的条件:
- 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
- 在映射文件中设置标签
<cache/>标签- 二级缓存必须在SqlSession关闭或提交之后有效
- 查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:
两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
MyBatis Plus
需要在启动类加@MapperScan(package = "mapper package"),或者在Mapper接口加上@Mapper
核心接口
Mapper
public interface UserMapper extends BaseMapper<User>{}
Service
public interface UserService extends IService<User>{}
ServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
核心注解
@TableName类名和表名对映
@TableId,insert的时候,MyBatis Plus用的是雪花算法
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
/* type IdType.AUTO 是数据库自增
IdType.ASSIGN_ID 雪花算法
*/
private Long id;
也可以全局配置
#MyBatis-Plus相关配置
mybatis-plus:
configuration:
#配置日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
#配置mp的主键策略为自增
id-type: auto
@TableFiled
@TableField(exist = false),表示此属性不是表的字段@TableField(fill = FieldFill.INSERT)自动更新@TableField("username")属性名和字段名不一致
@TableLogic逻辑删除
LambdaQueryWrapper
可以使用Lambda表达式
public void test(){
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
分页
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
LambdaQueryWrapper<VoucherOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(VoucherOrder::getId, 1);
Page<VoucherOrder> page = new Page<>(1, 2);
page(page, lambdaQueryWrapper);
本文由mdnice多平台发布