Mybatis框架-02
- Mybatis框架-02
- 动态SQL
- 多对一
- 实体类
- N+1策略
- 等值策略
- 一对多
- 实体类
- N+1策略
- 等值策略
- 缓存
- 一级缓存
- 二级缓存
- 逆向工程
Mybatis框架-02
动态SQL
什么是动态sql?
可根据传进来的值不同,动态的生成sql
语句。调用的是同一条sql
语句,从而达到sql
语句的复用。
比如说我要修改密码,sql
语句只能修改密码,其他的不能修改我的。当我需要修改其他的东西的时候,调用的还是这条sql
语句。他会动态的根据你的需要给你生成对应的sql
语句。
xml方式
<?xml version="1.0" encoding="UTF-8"?>
update user
name = #{name},
password = #{password},
age = #{age},
where id = #{id}
name like concat('%',#{name},'%')
and age = #{age}
delete from user where id in
#{id}
insert into user (name,password,age) values
(#{user.name},#{user.password},#{user.age})
注解方式:标签不是原来的那套标签了
@UpdateProvider
:type是你放在一个java类中完成,method是调用所对应的方法。
@UpdateProvider(type = UserSqlProvider.class,method = "update")
int update(User user);
@SelectProvider(type = UserSqlProvider.class, method = "selectListByCondition")
List selectListByCondition(User user);
@DeleteProvider(type = UserSqlProvider.class, method = "deleteByIds")
int deleteByIds(@Param("ids") Integer[] ids);
@InsertProvider(type = UserSqlProvider.class, method = "insertByBatch")
int insertByBatch(@Param("users") List users);
需要创建一个SQL
对象,或者是自己拼接sql
语句,返回一个String
package cn.zj.mybatis.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;
import cn.zj.mybatis.pojo.User;
public class UserSqlProvider {
public String update(User user) {
//SQL对象
SQL sql = new SQL();
sql.UPDATE("user");//相当于update user
//不需要加逗号
if(user.getName() != null) {
sql.SET("name = #{name}");//set会自动拼接后面的条件并且加上逗号
}
if(user.getPassword() != null) {
sql.SET("password = #{password}");
}
if(user.getAge() != null) {
sql.SET("age = #{age}");
}
sql.WHERE("id = #{id}");
System.out.println(sql.toString());
return sql.toString();
}
//多条件模糊查询
public String selectListByCondition(User user) {
SQL sql = new SQL();
sql.SELECT("*");//相当于 select *
sql.FROM("user");//相当于 from user
if(user.getName() != null) {
sql.WHERE("name like concat('%',#{name},'%')");//相当于where ... 默认两个字段之间使用and
}
if(user.getPassword() != null) {
sql.WHERE("password = #{password}");
}
if(user.getAge() != null) {
sql.OR();//默认是and连接
sql.WHERE("age = #{age}");
}
System.out.println(sql.toString());
return sql.toString();
}
//批量删除
public String deleteByIds(@Param("ids") Integer[] ids) {
SQL sql = new SQL();
sql.DELETE_FROM("user");//相当于 delete from user
StringBuilder sb = new StringBuilder();
//只能使用普通的循环
for (int i = 0; i < ids.length; i++) {
sb.append("#{ids["+i+"]},");
}
sb.deleteCharAt(sb.length()-1);//删除最后一个多余的逗号,是sb的长度-1
sql.WHERE("id in ("+sb.toString()+")");//没有的条件可以自己拼接
System.out.println(sql.toString());
return sql.toString();
}
//批量插入
public String insertByBatch(@Param("users") List users) {
//当sql对象的方法满足不了我们需求时,我们需要手动拼接
StringBuilder sb = new StringBuilder();
sb.append("insert into user(name,password,age) values ");
for (int i = 0; i < users.size(); i++) {
sb.append("(#{users["+i+"].name},#{users["+i+"].password},#{users["+i+"].age}),");
}
sb.deleteCharAt(sb.length()-1);//将最后一个逗号去掉
System.out.println(sb.toString());
return sb.toString();
}
}
多对一
实体类
department
package cn.zj.mybatis.pojo;
import java.util.List;
public class Department {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Department() {
super();
// TODO Auto-generated constructor stub
}
}
employee
package cn.zj.mybatis.pojo;
public class Employee {
private Integer id;
private String name;
//多对一
private Department dept;
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", dept=" + dept + "]";
}
public Employee() {
super();
// TODO Auto-generated constructor stub
}
}
N+1策略
public interface Many2OneMapper {
Employee selectByPrimayKey(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
等值策略
public interface Many2OneMapper {
Employee selectByPrimayKey(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
一对多
实体类
department
package cn.zj.mybatis.pojo;
import java.util.List;
public class Department {
private Integer id;
private String name;
private List emps;
public List getEmps() {
return emps;
}
public void setEmps(List emps) {
this.emps = emps;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department() {
super();
// TODO Auto-generated constructor stub
}
public Department(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + ", emps=" + emps + "]";
}
}
employee
package cn.zj.mybatis.pojo;
public class Employee {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
public Employee(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Employee() {
super();
// TODO Auto-generated constructor stub
}
}
N+1策略
public interface One2ManyMapper {
List selectByPrimayKey(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
等值策略
public interface One2ManyMapper {
List selectByPrimayKey(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
缓存
为什么需要缓存呢?
只有在持久层才有缓存说法。
当我们重复的去请求sql
都会做IO操作。如果我们每次都从数据库中去取数据的话。会打打的影响我们的效率。
如果我们将重复的请求放在缓存那里,让第一次请求在数据库中去取,第二次,第三次都让其取缓存中取,这样就大大的提高了我们查询的效率。
缓存分为一级缓存和二级缓存。
一级缓存
一级缓存是mybatis自带的,内置在sqlSession
对象中,默认是开启的。可以手动的设置关闭缓存。
session1.clearCache();
关闭缓存
二级缓存
一级缓存是SqlSession对象级别,在每一次会话中有效
二级缓存是 SqlSessionFactory级别,在整个应用都有效,可以在多个会话有效
MyBatis本身并没有实现二级缓存
二级缓存需要第三方缓存提供商的支持
Ehcache -第三方缓存(Hibernate框架默认就是支持)
学习:http://www.mybatis.org/ehcache-cache/
下载Ehcache : https://github.com/mybatis/ehcache-cache/releases
mybatis默认开启二级缓存;模拟一千次sqlSession对象的请求
导入ehcache包
导入依赖的日志包
xml中映射配置二级缓存
ehcache.xml配置(配置全局的二级缓存)
因为二级缓存可以缓存到文件(将对象序列化到本地),涉及到对象序列化,那么对应的javaBean对象就必须实现 。
命中率= 从缓存中获取数据的次数/ 查询的总次数
如 : 两次查询 从缓中获取一次
0.5 = 1/2;
0.666666 = 2/3;
命中率越高缓存效果越好
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - ==> Preparing: select * from user where id = ?
DEBUG [main] - ==> Parameters: 3(Integer)
DEBUG [main] - <== Total: 1
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.5
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.6666666666666666
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.75
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8333333333333334
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8571428571428571
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.875
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.8888888888888888
DEBUG [main] - Cache Hit Ratio [cn.zj.mybatis.mapper.UserMapper]: 0.9
逆向工程
就是可以根据数据库的字段动态的生成我们的实体类pojo
,还有一些常用的sql
语句。
首先需要安装mybatis插件在eclipse中。
然后new一个mybatis的generator,生成generatorConfig.xml配置文件。
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
逆向工程的使用
逆向工程没有生成插入方法的插入之后返回id值需手动添加。
@Test
public void testSelectByExample() {
// 1.创建sqlSession对象
SqlSession session = MybatisUtils.openSqlSession();
// 2.调用getMapper()得到代理对象
DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
DepartmentExample example = new DepartmentExample();
Criteria criteria = example.createCriteria();//创建限制对象;
//一个限制对象默认是用and连接两个字段,想要用or连接必须要创建两个限制对象。
criteria.andIdGreaterThan(2);
criteria.andNameLike("%部%");
List list = mapper.selectByExample(example);
for (Department department : list) {
System.out.println(department);
}
// 5.关闭连接
session.close();
}
@Test
public void testInsert() {
// 1.创建sqlSession对象
SqlSession session = MybatisUtils.openSqlSession();
// 2.调用getMapper()得到代理对象
DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
Department dept = new Department(null, "网络部");
int row = mapper.insert(dept);
System.out.println(row);
System.out.println(dept.getId());
// 4.提交事务
session.commit();
// 5.关闭连接
session.close();
}