(Plain Old Java Objects,普通老式 Java 对象)
package com.jt.springboot_demo2.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data //动态生成get/set/toString/equal
@Accessors(chain=true) //重写set方法,实现链式赋值
@NoArgsConstructor //无参构造
@AllArgsConstructor //全参构造
public class DemoUser implements Serializable {
private Integer id;
private String name;
private Integer age;
private String sex;
//this在运行期有效,代表当前对象 链式加载
public DemoUser setId(Integer id){
this.id = id;
return this ;
}
public void add(){
DemoUser d = new DemoUser();
d
.setAge(21)
.setId(12)
.setName("xy")
.setSex("man");
}
}
MyBatis
持久化:将内存数据保存到磁盘中
持久层:程序通过Dao(Data Access Objects)/Mapper层与数据库进行交互的层级
小结:基于ORM设计实现以对象的方式操作数据库
tips:resources文件下创建多层目录 cn/tedu/mapper
文件关系:测试类 --加载–> 主配置文件 --sqlsession得到–> mapper接口 --导入接口方法–> mapper实例(执行sql)
主配置文件mybatis-config.xml配置文件 路径:mybatis/mybatis-config.xml
测试类
public class TestMybatis {
@Test
public void demo1() throws IOException {
//读取核心配置文件
//指定配置文件地址
String resource = "mybatis/mybatis-config.xml";
//通过io流,加载指定的配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//动态生成SqlSessionFactory
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlsession,类比JDBC链接,执行sql语句最小单位
SqlSession ss = ssf.openSession();
//获取mapper接口,使用接口调用demoUserMapper.xml执行sql(底层JDBC执行sql)
DemoUserMapper m = ss.getMapper(DemoUserMapper.class);
//封装对象,返回结果集
List userList = m.findAll();
System.out.println(userList);
ss.close();
}
//封装
SqlSessionFactory ssf;
@BeforeEach //@BeforeEach在@Test执行之前执行
public void init() throws IOException {
InputStream s = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
ssf = new SqlSessionFactoryBuilder().build(s);
}
@Test
public void testFindByName(){
//SqlSession sqlSession1 = ssf.openSession(true);
SqlSession sqlSession= ssf.openSession();
DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
String s = "王昭君";
List userList= mapper.findByName(s);
System.out.println(userList);
sqlSession.close();
}
@Test
public void testSaveUser(){
SqlSession sqlSession= ssf.openSession();
DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
DemoUser user = new DemoUser(null,"xy",12,"男");
int rows = mapper.saveUser(user); //方法做"更新"操作默认返回修改行数
if(rows>0){
System.out.println("影响行数"+rows);
sqlSession.commit();
}
sqlSession.close(); //更新操作时,需要手动提交事务
}
}
实体对象
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class DemoUser implements Serializable {
private Integer id;
private String name;
private Integer age;
private String sex;
}
mapper接口
mapper持久层下的DemoUserMapper接口
public interface DemoUserMapper {
public List findAll(); //在测试类中调用,在xml中实现
DemoUser findOne(int id);
}
mapper实例
demoUserMapper.xml实例 路径:mybatis/mappers/demoUserMapper.xml
环境select * from demo_user
环境:pom.xml导入jar包
多值传递4.0.0 com.jt springboot_demo1 0.0.1-SNAPSHOT springboot_demo1 Demo project for Spring Boot 1.8 UTF-8 UTF-8 2.4.1 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.mybatis.spring.boot mybatis-spring-boot-starter 2.2.0 mysql mysql-connector-java org.springframework.boot spring-boot-devtools org.projectlombok lombok org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 1.8 UTF-8 org.springframework.boot spring-boot-maven-plugin 2.4.1 com.jt.springboot_demo3_mybatis.SpringbootDemo3MybatisApplication repackage repackage
Mybatis默认支持单值传参,多值要转换为单值
Mybatis多值传参默认采用下标方式获取数据,应封装
封装策略:
1、封装为实体对象,属性只出现一次(只能传一个对象)
2、常用Map集合 Map
3、注解@Param(“key”) Object value (底层封装为Map)
相同类型的数据多值传递1、array
2、List
3、Map
//测试类传入数组参数
int[] ids = new int[]{1,3,4,5};
int rows = mapper.deleteIds(ids);
//传入List,只需要改collection参数
List list = new ArrayList();
int rows = mapper.deleteList(list);
//传入map,只需要改collection参数
Map map = new HashMap();
map.put("ids",List);
int rows = mapper.deleteM(map);
集合遍历foreach
delete form demo_user where id in #{id}
map批量更新
public void testUpdate1(){ SqlSession sqlSession = ssf.openSession(true); DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class); Map map = new HashMap<>(); String[] arr = {"小乔","大乔","王昭君"}; map.put("names", arr); map.put("age", 18); map.put("sex", "女"); mapper.updateUser(map); sqlSession.close(); }
注意事项 #号与$符的区别update demo_user set age = #{age},sex = #{sex} where name in ( #{name} )
对象或map集合传入参数可#{}直接使用
-
#{}以数据为参数,默认有预编译的效果,默认加了" " ,防止sql注入攻击
-
${}以字段名称为参数,直接传值,慎用(写死,不传参数)
> >大于< <小于& &与
转义标签体
#{minage} and age < #{maxage}]]>
SQL
大小写转换快捷键:ctrl+shift+u
like模糊查询
select * from demo_user where name like "%"#{s}"%"
Mybatis优化设置
配置pojo类别名
简化resultType的值
SQL标签SELECT * FROM DEMO_USER WHERe NAME LIKE "%"#{S}"%" ORDER BY AGE DESC
优势:缩减xml文件大小,代码结构相对简单
弊端:只能抽取公共部分,代码可读性差
Mybatis-动态SQLselect * from demo_user where name like "%"#{s}"%" order by age desc
where、if标签:去除多余and/or
select * from demo_user name = #{name} and age = #{age} and sex = #{sex}
set标签、if标签:去除多余逗号
update demo_user where id = #{id} name = #{name}, and age = #{age}, and sex = #{sex}
choose、when、otherwise标签
不想把全部条件当作if的判断(if-else),只执行一个条件
配置别名select * from demo_user where name = #{name} sex = #{sex}
@Alias("DemoUser")public class DemoUser implements Serializable { private Integer id; private String name; private Integer age; private String sex;}
resultType与resultMap
resultType:单表查询时字段与属性名一致
resultMap:解决字段(结果集)与属性名称不一致的问题
select * from dept
*Mybatis关联关系(多表查询)select * from dept
关联查询效率高于子查询
一对一关联查询:sql复杂,封装简单
select * from emp left join dept on dept.`dept_id`=emp.`dept_id`
子查询:sql简单,封装复杂
一对多select * from emp select * from dept where dept_id = #{dept_id}
关联查询
1、
select d.dept_id,d.dept_name,e.id,e.name,e.age from dept d left join emp e on d.`dept_id`=e.`dept_id`
2、
public class Rights extends basePojo{ private Integer id; private String name; private Integer parentId; private String path; private Integer level; private List children; //不是表格固有属性,一对多:使用list集合}
SELECT p.id,p.name,p.parent_id,p.path,p.level,p.created,p.updated, c.id c_id,c.name c_name,c.parent_id c_parent_id, c.path c_path,c.level c_level,c.created c_created, c.updated c_updated FROM (SELECt * FROM rights WHERe parent_id=0)p LEFT JOIN rights c ON p.id = c.parent_id
子查询
驼峰自动映射SELECT * FROM rights WHERe parent_id=0 SELECT * FROM rights WHERe parent_id=#{id}
关联查询生效需要开启:autoMapping=“true”
最后保留主键:,为以后拓展
Mybatis的缓存机制
降低访问物理设备次数,提高用户响应速度
一级缓存默认开启,可以在同一个SqlSession对象中,查询相同数据,实现数据共享
规则:同一个SqlSession内部有效
二级缓存默认开启,需要手动标识
规则:同一个SqlSessionFactory内部有效
在mapper实现类的xml文件中添加
说明:sqlSession查数据后交给一级缓存
sqlSession业务逻辑执行成功并且关闭
二级缓冲才能起作用
增删改会删除一二级缓存
总结ORM(Object Relational Mapping)对象关系映射
Mybatis是一个优秀的持久层框架,将接口和 Java 的 POJO映射成数据库中的记录。
补充 参数mybatis利用下标取值,一个参数时,名称任意 #{任意} 但注意开发规范
map或@Param必须用key取值value #{key}
对象传参 #{属性}
动态代理JDK动态代理
代理者必须实现接口,代理对象是目标对象的实现类或兄弟元素
CGLIB代理
不管是否实现接口接口,代理对象是目标对象的子类
spring自动导入jar包
mapper接口的说明DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
接口不可创建对象,mapper为JDK动态代理对象
调用代理对象与接口功能一致



