文章目录
Mybatis部分
1:@Param源码
打上断点之后进入debug,
会进入如下这个方法,然后回调用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
}
之后进入这个invoke方法之后会继续进入
然后就可以发现这是一个switch判断
根据comman参数的type类型判断当前执行的是那种类型的sql语句.
ParamNameResolver类的构造器将会返回names,那么来研究一下这个方法都做了些什么
可以发现names里面就是一个键值对,其中键为0,1…,值为你传递的参数
注意这里的 String genericParamName = “param” + (i + 1);
就是由于这句话因此Mybatis中当传递多个参数的时候为什么是使用param1,param2来区分不同的参数
2:#{}与${}的区别
#{}使用的是占位符方式,而${}使用的是字符串拼接技术.
因此#{}再注入数据之后会自动加上 单引号,并且由于我们传递过来的参数大部分为string类型,使得#{}的使用更多一点,并且其还能防止数据注入的问题.
${}使用的是字符串拼接技术,我们再JDBC的时候学习过如果你使用字符串拼接作为sql语句,那么你是需要自己去添加单引号的, ${}就是这样,因此再使用它的时候他不会自动添加单引号,你需要手动添加.
但是有些时候我们的查询等操作是不需要添加单引号的,
1:以表名为查询对象
例如我们根据表名查询,那么我们的表名是不能有单引号的,因此如果你使用#{}就会报错,这个时候就必须使用 ${}
2:查询时参数放入到in中
同时,由于#{}自动添加单引号的特性,使得如果我们要使用 select * from table where id in (#{id}),就会导致由于#{id}自动会添加单引号的问题变成in(‘1,2,3’),而正确写法是in(1,2,3),因此会导致查询不到数据但是不会报错,毕竟加上单引号后就变成了字符串,相当于匹配字符串,没什么问题.
因此我们需要使用 in ( ${id} ) ,这样就会自动拼接为 in (1,2,3)因此能查询到数据
3:需要模糊查询数据的时候
众所周知模糊查询的条件放在单引号中,但是如果使用#{}由于其被放在了单引号中,因此#{}本来以占位符?来占位,就会被单引号修饰变成一个字符串,因此这个时候他就认为没有需要填充数据的地方,就会报错了
Try setting a different JdbcType for this parameter or a different configuration property.
这个时候使用${}就没有问题
3:查询一对多或者多对一的数据
数据库中经常会有一个表中的属性与另外几个表有关系.
例如emp和dept表,一个emp只会有一个dept,但是多个emp可以同时对应一个emp(多对一).
同时也有一个dept对应多个的emp,也就是一个部门可以有多个emp.
即一对多.
用Java的对象表现出来就是这样.
Dept类
public class Dept {
private Integer did;
private String deptName;
private List<Emp> emps
}
Emp类
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
}
可以发现不同的地方在于Emp中的属性Dept是对象.
但是多个Emp可以同时对应同一个Dept,因此当有多个Emp对象的时候,这是一个多对一的关系.
而Dept中的emps属性是List集合,其中包含了多个的Emp对象,也就是说明了一个Dept中可以包含多个Emp,也就是一对多的关系.
但是我们的表一般不可能直接包含另一个表,而是通过包含另一个表中的某个主键来将自己的这个属性映射到另一个表中去.因此如果我们要查询某个员工,我们必须同时查询到另一个Dept表中的数据才能做到成功的把员工表中的所有消息都输出,这其中包括了Dept的消息.
因此我们肯定需要多表查询的操作,多表查询我们一般用left join等方法.
解决多对一
这种多对一对应的就是Emp中包含的Dept对象,那么如何在查询Emp对象的同时给其中的dept属性赋值呢?
Mybaits提供了三种方法
1:级联属性赋值
这种方式其实就是直接两个表联合起来一起查询,left join,懂得都懂好吧,然后把查询到的dept的数据通过result标签中的property属性直接赋值给dept.did与dept.deptName,这样只要在表中查询到了符合sql表达式的数据就会把这条数据给他插入到Emp对象中去
<!--
处理多对一映射关系一:级联属性赋值
-->
<resultMap id="getEmpAndDept1" type="emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<select id="getEmpAndDept" resultMap="getEmpAndDept1">
select *
from my_emp
left join my_dept on my_emp.did = my_dept.did
where my_emp.eid = #{eid}
</select>
2:通过association标签
和上面那种差不多,不多赘述
<!--
处理多对一映射关系二:通过association
association:处理多对一的映射关系
property:需要处理多对的映射关系的属性名
javaType:该属性的类型
-->
<resultMap id="getEmpAndDept2" type="emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<select id="getEmpAndDept" resultMap="getEmpAndDept2">
select *
from my_emp
left join my_dept on my_emp.did = my_dept.did
where my_emp.eid = #{eid}
</select>
调用结果也一样
3:分布查询
这种方法将查询步骤分为两步,当你需要为dept属性进行填充的时候,他就会去调用DeptMapper的方法把你要求查询的对应的以did为查询条件的数据返回回来,然后你就可以用它返回回来的数据去填充你的dept属性了.
这种方法有一个好处就是你可以开启延迟加载,延迟加载就是说当你需要用到dept这个属性的时候他才会去调用发布查询中的第二个sql语句去查询Dept表中的数据,如果你不需要,那么只会查询Emp表中的数据
<settings>
<!--将下划线自动映射为驼峰 em_pname:emPname-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<resultMap id="getEmpAndDeptByStepOne" type="emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<!--
select:设置分布查询的sql的唯一标识(namespace.sqlid或者mapper接口的全类类名.方法名)
column:设置分布查询的查询条件
property:需要填充的对象
fetchType:当开启了全局的延迟加载之后,可以通过这个属性手动的控制延迟加载功能
-->
<association property="dept"
select="com.learn.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"
fetchType="lazy">
</association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepOne">
select *
from my_emp
where eid = #{eid}
</select>
DeptMapper文件
<select id="getEmpAndDeptByStepTwo" resultType="dept">
select *
from my_dept
where did = #{did}
</select>
这里需要介绍一下发布查询中association中的这几个参数
property:就是你需要填充的要去另外一个表中查询的对象
select:因为是分布查询,所以要去调用另一个Mapper文件中的方法来查询其管理的表数据,这里我要查询Dept表的数据,因此我的select属性中填充的是能得到dept对象的接口方法
column:这个属性也就是你传递给要去另一个表中查询数据的查询条件参数,这里我把要查询的emp对象对应的emp表中的did属性作为查询条件去查询对应dept属性,查询到之后就会把这个查询到的数据给他填充到emp对象的dept域中去.
这就是多对一的解决方式.
解决一对多
一对多对应的是Dept对象中的emps,因为一个Dept可以有多个的Emp属于它,因此它可以包含多个的Emp对象,因此需要一个List集合去包含它.
1:使用collection标签
这种方法和上面那种使用association根标签填充dept对象的方法差不多,也是通过多表查询把查询到的数据填充到emp属性里面
<resultMap id="getDeptAndEmpMap" type="dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<!--
collectiojn:处理一对多的映射关系
ofType:表示该属性所对应的集合中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<select id="getDeptAndEmp" resultMap="getDeptAndEmpMap">
select *
from my_dept
left join my_emp on my_dept.did = my_emp.did
where my_dept.did = #{did}
</select>
2:使用分布查询
一对多的发布查询和刚才的多对一的发布查询差不多 ,不多赘述
<resultMap id="getDeptAndEmpByStepOne" type="dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="com.learn.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpByStepOne">
select *
from my_dept
where did = #{did}
</select>
4:动态SQL
根据标签中的内容是否为空来判断是否需要添加判断语句
1:使用if标签
<select id="getEmptyByCondition" resultType="emp">
select * from my_emp where 1=1
<if test="empName!=null and empName!=''">
and emp_name=#{empName}
</if>
<if test="age!=null and age!=''">
and age=#{age}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
<if test="email!=null and email!=''">
and email=#{email}
</if>
</select>
2:使用where标签
当where标签中有内容的时候,会自动生成where关键字,并且将内容前多余的and或or去掉,当where标签中没有内容时,此时where标签没有任何效果.并且需要注意,where标签不能将其中内容后的多余and或者or去掉
<select id="getEmptyByCondition" resultType="emp">
select * from my_emp
<where>
<if test="empName!=null and empName!=''">
emp_name=#{empName}
</if>
<if test="age!=null and age!=''">
and age=#{age}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
<if test="email!=null and email!=''">
and email=#{email}
</if>
</where>
</select>
3:trim标签
prefix|suffix:将trim标签中内容前面或后面添加指定内容
suffixOverrides|prefixOverrides:将trim标签中内容前面或者后面去掉指定内容
若标签中没有内容的时候,trim标签也没有任何效果
<select id="getEmptyByCondition" resultType="emp">
select * from my_emp
<trim suffix="" prefix="where" suffixOverrides="and|or">
<if test="empName!=null and empName!=''">
emp_name=#{empName} and
</if>
<if test="age!=null and age!=''">
age=#{age} and
</if>
<if test="sex!=null and sex!=''">
sex=#{sex} and
</if>
<if test="email!=null and email!=''">
email=#{email}
</if>
</trim>
</select>
4:choose,when,otherwise
<select id="getEmptyByChoose" resultType="emp">
select * from my_emp
<where>
<choose>
<when test="empName!=null and empName!=''">
emp_name=#{empName}
</when>
<when test="age!=null and age!=''">
age=#{age}
</when>
<when test="sex!=null and sex!=''">
sex=#{sex}
</when>
<when test="email!=null and email!=''">
email=#{email}
</when>
<otherwise>
did = 1
</otherwise>
</choose>
</where>
</select>
5:foreach批量操作
* collection:设置需要循环的数组或集合
* item:表示数组或集合中的每一个数据
* separator:循环体之间的分割符
* open:foreach标签所循环的所有内容的开始符
* close:foreach标签所循环的所有内容的结束符
<delete id="deleteMoreByArray">
delete from my_emp where
<foreach collection="eids" item="eid" separator="or">
eid = #{eid}
</foreach>
</delete>
<insert id="insertMoreByList">
insert into my_emp values
<foreach collection="emps" item="emp" separator=",">
(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>
5:mybatis的逆向工程
官网网址
首先这个东西需要先导入对应的jar包,使用的是maven工程
maven工程中加入这些语句
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
如果需要使用MBG需要先创建一个名字为generatorConfig.xml的文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test"
userId="root"
password="root">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.learn.ssm.bean" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.learn.ssm.dao" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="my_emp" domainObjectName="Emp"/>
<table tableName="my_dept" domainObjectName="Dept"/>
</context>
</generatorConfiguration>
之后双击加载MBG即可
也可以使用java来创建,如果用java来创建那么就只需要导入一个jar包而不需要写上build等语句在maven中
同时由于使用MBG生成的注释比较多,因此可以选择关闭注释
Mybatis-Plus
1:基本使用
Mybatis-Plus的使用只需要在你需要添加功能的接口上继承BaseMapper即可,同时要求接口对应的pojo实体类对象的表名要与实体类对象类名一样.
2:分页功能
如果需要使用Mybatis的分页功能,那么需要开启Mybatis-Plus的分页功能拦截器.并加上@Configuration注解使得启动类能加载到他.
开启拦截器之后使用MybatisPlus内置的分页接口即可
同时如果想看到MybatisPlus的运行语句,那么需要开启日志
3:DQL编程控制
条件查询
可以发现BaseMapper接口中有着大量的方法,这些方法的参数为Wrapper,而这对象代表着对数据库查询时所携带的查询条件.
查询投影
查询投影即表示查询那些信息,即选择需要查看的字段
同时如果遇到不好使用这种方法来查询的,可以直接在对应的dao接口中用mybatis的注解的方式来解决
各种查询条件
1:等值匹配
@Test
public void eq(){
LambdaQueryWrapper<Book>lqw=new LambdaQueryWrapper<>();
lqw.eq(Book::getName,"helo").eq(Book::getType,"sad");
System.out.println(bookDao.selectList(lqw));
}
2:范围查询
@Test
public void between(){
LambdaQueryWrapper<Book>lqw=new LambdaQueryWrapper<>();
lqw.between(Book::getNumber,10,50);
System.out.println(bookDao.selectList(lqw));
}
3:模糊匹配
@Test
public void like(){
LambdaQueryWrapper<Book>lqw=new LambdaQueryWrapper<>();
lqw.like(Book::getName,"e");
//其中likeLeft/likeRight会使用左/右百分号
System.out.println(bookDao.selectList(lqw));
}
更多其他可以进行的查询条件可以搜索
6.条件查询介绍
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
@SpringBootTest
publicclassQueryWrapperTests {
@Autowired
privateUserMapperuserMapper;
}
2、测试用例
2.1 ge、gt、le、lt、isNull、isNotNull
@Test
public void testQuery() {
QueryWrapperqueryWrapper = newQueryWrapper<>();
queryWrapper
.isNull(“name”)
.ge(“age”, 12)
.isNotNull(“email”);
int result = userMapper.delete(queryWrapper);
System.out.println("delete return count = " + result);
}
2.2 eq、ne
注意:seletOne()返回的是一条实体记录,当出现多条时会报错
@Test
public void testSelectOne() {
QueryWrapperqueryWrapper = newQueryWrapper<>();
queryWrapper.eq(“name”, “Tom”);
Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
System.out.println(user);
}
2.3 between、notBetween
包含大小边界
@Test
public void testSelectCount() {
QueryWrapperqueryWrapper = newQueryWrapper<>();
queryWrapper.between(“age”, 20, 30);
Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
System.out.println(count);
}
2.4 like、notLike、likeLeft、likeRight
selectMaps()返回Map集合列表,通常配合select()使用
@Test
public void testSelectMaps() {
QueryWrapperqueryWrapper = newQueryWrapper<>();
queryWrapper
.select(“name”, “age”)
.like(“name”, “e”)
.likeRight(“email”, “5”);
List<Map<String, Object>>maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
maps.forEach(System.out::println);
}
2.5 orderBy、orderByDesc、orderByAsc
@Test
public void testSelectListOrderBy() {
QueryWrapperqueryWrapper = newQueryWrapper<>();
queryWrapper.orderByDesc(“age”, “id”);
Listusers = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
1、查询方式
查询方式 说明
setSqlSelect 设置 SELECT 查询字段
where WHERE 语句,拼接 + WHERE 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like 模糊查询 LIKE
notLike 模糊查询 NOT LIKE
in IN 查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull IS NOT NULL
groupBy 分组 GROUP BY
having HAVING 关键词
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last(“LIMIT 1”)
多表联查
MybatisPlus只是在原有Mybatis的基础上增强了单表查询的功能,因此如果需要多表查询,那么依旧需要编写配置文件
mybatisplus默认的mapper配置文件的路径在类路径下的mapper目录中的所有xml文件
4:DML编程控制
id生成策略
NONE表示不启用,也就是默认值,表示按照MybatisPlus默认的id生成策略
AUTO表示使用自增
INPUT表示要求必须手动传递一个id过去
ASSING_ID表示使用雪花算法得到一个ID,对应实体类必须使用Long类型,数据库字段需要使用binary或者varchar来接受
也可以用配置文件来统一配置实体类中的id属性的注解属性
多记录操作
提供多数据的id即可
@Test
public void deleteBatch(){
List<Long>list= Arrays.asList(2L,3L,4L);
bookDao.selectBatchIds(list);
bookDao.deleteBatchIds(list);
}
逻辑删除
乐观锁
首先需要在数据库表中添加一个字段用于表示乐观锁操作的字段.
之后就可以在对应的实体类中添加属性来对应到数据库中的字段
为了开启乐观锁的效果,需要配置乐观锁的拦截器
之后如果想要修改version这个字段,那么首先我们得先保证得到version这个属性,否则乐观锁不会启动
乐观锁实现
用户1进来后修改数据为它的部分之后,version的值就已经改变了,当用户2进来操作后,它拿到的还是原先的version值,因此它的判断条件会失败,因此无法成功再次修改数据,因此用户1成功得到这个数据.
通用枚举
表中的有些字段值是固定的,例如性别(男或女),此时我们可以使用Mybatis-Plus的通用枚举来实现.
首先编写一个枚举类,然后把需要向数据库中插入的对应的要插入的类型加上
@EnumValue注解,之后就把会这个注解对应的属性对应的枚举的值插入到数据库中而不是把整个枚举类型插入到数据库.
当然如果需要使用这个功能,需要在配置文件中开启对通用枚举的扫描
5:清爽控制台以及查看对应SQL语句的配置
6:加快pojo类开发
可以在maven中导入坐标
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
之后就可以使用注解给实体类添加有参无参构造函数以及getter/setter以及equals等方法
7:字段映射与表名映射
同时如果所有表名的前缀都一样,那么可以使用配置文件来统一配置前缀
8:代码生成器
首先导入两个核心引擎
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
package com.example.ssm_;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
/**
* @author: Serendipity
* Date: 2022/5/11 12:47
* Description:
*/
public class Generator {
public static void main(String[] args) {
//1.获取代码生成器的对象
AutoGenerator autoGenerator = new AutoGenerator();
//设置数据库相关配置
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
autoGenerator.setDataSource(dataSource);
//设置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir("D:\\desktopfile\\ssm_\\src\\main\\java"); //设置代码生成位置
globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
globalConfig.setAuthor("Serendipity"); //设置作者
globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
globalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称
globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);
//设置包名相关配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.example"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
packageInfo.setEntity("pojo"); //设置实体类包名
packageInfo.setMapper("dao"); //设置数据层包名
autoGenerator.setPackageInfo(packageInfo);
//策略设置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("tbl_book"); //设置当前参与生成的表名,参数为可变参数
strategyConfig.setTablePrefix("tbl_"); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格
strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名
strategyConfig.setEntityLombokModel(true); //设置是否启用lombok
autoGenerator.setStrategy(strategyConfig);
//2.执行生成操作
autoGenerator.execute();
}
}
9:多库查询
多库查询实现的是通过制定不同的数据源来将对应的方法或者对应的类对数据库进行的CRUD进行换源.也就是类或方法被指定了数据源后就会查询对应的数据源对应的数据库,而不是只能无脑的查一个数据库.
首先需要导入多库查询所需要的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
YML文件开启多库查询
spring:
datasource:
dynamic:
strict: false
primary: master
datasource:
master:
url: jdbc:mysql://localhost33-6/test?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
slave_1:
url: jdbc:mysql://localhost33-6/mealsale?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
service包
10:MybatisX
这是一个IDEA中的插件
MybatisX进行的是有选择性的添加,因此你需要什么语句去对应的mapper类中进行添加即可
11:自动填充
需求描述:
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作
1.1数据库修改
在User表中添加datetime类型的新的字段 create_time、update_time
而java中的user对象要求使用的类型是java。Util。Date,而不是sql。Date。
如果你使用localdate,
1.2实体类修改
实体上增加字段并添加自动填充注解
@TableField(fill = FieldFill.INSERT)
private Date createTime; //create_time
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
1.3实现元对象处理器接口
注意:不要忘记添加 @Component 注解
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//mp执行添加操作,这个方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//mp执行修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}