MyBatis
第一部分 MyBatis基础
这些基础知识是学习MyBatis的前提
1. jdk动态代理
直接上代码,也不啰嗦了
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyFactory implements InvocationHandler {
Object target;
public void setTarget(Object target) {
this.target = target;
}
public Object getProxy(){
return java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
System.out.println("代理方法执行了");
return result;
}
}
2. CGLIB动态代理
cglib动态代理也叫类代理,代理目标没有实现接口的话,就只能使用CGLIB代理
实现使用继承的特性,子类来重写父类方法
3. 什么是MyBatis
可以让程序员专注于sql语句的ORM框架
第二部分 hello MyBatis
跟随老师的步伐,初步编写一个MyBatis测试demo
目标
- 调通配置,能从数据库获取到数据
1.步骤
- 创建maven工程,导入mybatis以及数据库相关依赖
- 编写与数据库表对应的实体类
- 编写一个实体类对应的mapper.xml(也就是我们的sql)
- 编写mybatis配置文件 mybatis-config.xml
- 编写测试demo,调通数据
2. 实现
① 导入依赖
<!-- 测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
② 实体类
简单又实惠
@Data
public class Student {
private int id;
private String name;
private int teacherId;
private Integer delFlag;
}
③ 对应的mapper.xml
也就是我们实体类Student对应的增删改查sql
我一般创建在 resource/mapper 下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--头文件一定不能掉-->
<!--命名空间-->
<mapper namespace="student">
<!-- 这句sql的名称-->
<select id="list" resultType="student">
SELECT * FROM student WHERE del_flag = 0;
</select>
</mapper>
④ 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>
<!--设置mybatis日志输出,可以在控制台看到sql具体内容-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册表别名-->
<typeAliases>
<!--package指定实体类所在的包,并使用驼峰命名法起别名,这样的话在mapper.xml文件中就可以直接写student了-->
<package name="com.llz.entity"/>
</typeAliases>
<!--数据库链接环境-->
<environments default="development">
<!--环境1-->
<environment id="development">
<!--配置事务设定方式: JDBC-程序员自己决定-->
<transactionManager type="JDBC"/>
<!--设置数据库链接方式: POOLED-使用数据库连接池-->
<dataSource type="POOLED">
<!--sql链接参数-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test01?characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 配置自己mapper.xml的位置-->
<mappers>
<!--xml文件虽然放在resources下但是包名的目录结构必须和接口一样-->
<!--<package name="com.llz.mapper"/>-->
<mapper resource="mapper\StudentMapper.xml"/>
</mappers>
</configuration>
⑤ 测试demo
import com.llz.entity.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test01 {
@Test
public void Test01() throws IOException {
// 加载mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 获取sessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlsession
SqlSession sqlSession = sessionFactory.openSession();
// 指定对应的方法获取数据 参数就是我们mapper的 namespace + id
List<Student> objects = sqlSession.selectList("student.list");
// 输出
objects.forEach(System.out::println);
// 关闭sqlSession
sqlSession.close();
}
}
3. 将实现修改为动态代理
在上述实现过程中,sqlsession直接调用xml文件的指定方法,并没有面向接口编程
所以要进行修改
① 为mapper.xml添加mapper接口
mapper接口的位置一般写在与entity同级的mapper包下
public interface StudentMapper {
List<Student> list();
}
② 修改mapper.xml的映射
也就是修改mapper的namespace,让他指定绑定的接口
<!--命名空间,要写全类名-->
<mapper namespace="com.llz.mapper.StudentMapper">
<!-- 这句sql的名称-->
<select id="list" resultType="student">
SELECT * FROM student WHERE del_flag = 0;
</select>
</mapper>
③ 获取代理对象
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession();
// 获取接口代理对象 调用方法获取数据 参数就是我们要代理的对象
StudentMapper sessionMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> objects = sessionMapper.list();
objects.forEach(System.out::println);
sqlSession.close();
第三部分 MyBatis语法
1. 基础CRUD
① 查询
查询必须写返回值类型
<select id="xxx" resultType="Employee">
select
*
from employee;
</select>
② 修改
<update id="update1">
update employee
set id=#{id},name=#{name}
where id=2
</update>
<update id="update2">
update employee
<set>
<if test="name!=null">
name=#{name}, //每个语句后面都要加 “,” 要不然会报错
</if>
<if test="dId!=null">
d_id=#{dId},
</if>
</set>
where id=#{id}
</update>
③ 删除
<delete id="xxx">
delete from employee
where id=#{id}
</delete>
④ 插入
<insert id="XXX">
insert into
employee (id,name)
values (#{id},#{name})
</insert>
// 插入同时返回主键id 需要使用两个属性 useGeneratedKeys="true" keyProperty="u_id" 主键名
<insert id="XXX" useGeneratedKeys="true" keyProperty="u_id">
insert into
employee (id,name)
values (#{id},#{name})
</insert>
<insert id="XXX" useGeneratedKeys="true" keyProperty="u_id">
<selectKey keyColumn="id" keyProperty="u_id" resultType="String" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into
employee (id,name)
values (#{id},#{name})
</insert>
2. 动态标签
① if 语句
多个条件可同时生效的
基础结构:
<if test="id!=null"> <!--只有条件通过 才会拼接sql-->
and id like #{id}
</if>
例如:
<select id="get" resultType="EmployeeDomain">
select * from employee where 1=1
<if test="id!=null">
and id like #{id}
</if>
<if test="name!=null">
and name like #{name}
</if>
<if test="d_id!=null">
and d_id like #{d_id}
</if>
</select>
② choose 语句
基础结构:
<choose>
<when test="d_id!=null">
d_id like #{d_id}
</when>
<otherwise>
1=1
</otherwise>
</choose>
<select id="get2" resultType="EmployeeDomain">
select * from employee
<where>
<choose>
<when test="id!=null"> <!--只有一个when会生效-->
id like #{id}
</when>
<when test="name!=null">
name like #{name}
</when>
<when test="d_id!=null">
d_id like #{d_id}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
③ foreach 语句
基础结构:
collection 要遍历的集合
item 每个元素的代名
open 以什么开头
close 以什么结束
separator 循环体间隔
index list中是每个元素的序号,Map中是key
<foreach collection="list" item="id" open="(" close=")" separator="," index="">
#{id}
</foreach>
<select id="getin" resultType="EmployeeDomain">
select * from employee where
id in
(
<foreach collection="list" item="id" separator=",">
#{id}
</foreach>
)
</select>
④ sql 抽取
抽取公共 sql,配合 include使用提高利用率
<sql id="emp_prop"> //id是引用时的表示
。。。。。。
</sql>
⑤ include 引入
<include refid="emp_prop"></include>
⑥ where
就是sql里Where的标签形式
<where>
<if test="">
</if>
...
</where>
⑦ set
就是set标签
<set>
<if test="...">
...,
</if>
<if test="...">
...,
</if>
<if test="..."> // 当mybatis检测是最后一个参数时会去掉‘,’
...,
</if>
</set>
⑧ resultMap 手动映射
// 手动映射 那些需要映射写那些 不需要的可以不写 type就是指定要映射的实体类
<resultMap id="studentMap" type="student">
<id property="id" column="id"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
// 注意引入方法 resultMap
<select id="list" resultMap="studentMap">
SELECT *
FROM student
WHERE del_flag = 0;
</select>
3. 参数获取
1.两种方法
1.#{}相当于? 能防止sql注入
2.${}直接拼串 不能防止sql注入 不能预编译的位置可以使用 比如:列名
2.单参数
1.普通值
#{参数名} 直接获取值
2.对象
#{属性名} 获取属性值
3.多参数
1.普通值
#{arg0} #{arg1} 获取值
2.对象
#{对象形参名.属性名} 获取属性值
4.List集合
1.直接索引
#{参数名[索引]}
5.Map集合
1.直接键名
#{参数名.键名}
4. 返回值类型
1.List
返回值类型是元素类型
2.Map
返回值类型是value的类型
如何规定key,在接口方法上添加注解 @MapKey("属性名") 就可以指定key名
第四部分 缓存
mybatis一共有两级缓存,默认开启一级缓存
1. 一级缓存
一级缓存作用域是sqlSession
当我们执行sql之后,数据会保存在sqlSession中
缓存失效
- 进行 **增删改 **操作,会清除清除一级
- 调用sqlsession执行不同的sql语句
- 执行clearCache()方法,清除缓存
- 调用不同的sqlsession方法,缓存不会生效
2. 二级缓存
二级缓存作用域是SqlSessionFactory,默认并没有开启
如何开启二级缓存?
- 在mybatis配置文件中开启缓存,默认开始,不用配置
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- 在需要开启缓存的mapper.xml中添加,<cache/>标签
<mapper namespace="com.llz.mapper.StudentMapper">
<cache/>
...
</mapper>
- 最关键的一步,sqlSession必须关闭或提交数据才能保存到SqlSessionFactory中
缓存失效
- 进行 **增删改 **操作,会清除清除二级缓存
第五部分 追源码
(待完成)
1. new SqlSessionFactoryBuilder().build()
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
解析xml标签内容
① properties
读取配置文件
② settings
③ typeAliases
- 先判断子节点是package在判断是否是typeAlias
- 如果是package,进行包扫描,获取.class结尾的文件,通过类加载器,创建出对应的class文件,判断该class是否有Alias注解,没有的话,使用alias.toLowerCase(Locale.ENGLISH),将type的首字母转为小写,放入TypeAliasRegistry.Map<String, Class<?>> typeAliases中
④ environments
⑤ mappers
- 判断子节点优先级 package>resource>url>class
- 如果是package那么会扫描包得到所有文件,获取.class结尾的文件,通过类加载器,创建出对应的class文件,通过type创建MapperProxyFactory,
MyBatis-Plus
在mybatis的基础上做了功能增强
第一部分 hello mybatis-plus
1. 实现步骤
- 创建spring boot 项目,导入相关依赖
- 在yml文件中配置 数据库配置
- 创建entity、mapper、添加扫描
- 测试
2. 实现
① 创建spring boot 项目,导入依赖
spring boot这里使用2.6.7版本
<!--lombok依赖(为了偷懒),注意要下载相关插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驱动,没有指定版本,默认使用springboot内置版本,可以在spring boot依赖中查看(2.1以上内置为8版本)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--引入druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.11</version>
</dependency>
② 配置yml
在resources下创建application.yml文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#如果驱动版本为8.0选择带‘cj’的名称 5.0不用
driver-class-name: com.mysql.cj.jdbc.Driver
#mysql是8.0版本需要带时区serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/test_local?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
#mybatis-plus配置
mybatis-plus:
configuration:
#日志配置,控制台可以输出sql语句
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#mapper.xml映射文件路径 这是默认路径,可以不写
mapper-locations: classpath*:/mapper/**/*.xml
③ 创建entity、mapper
- 实体类对应数据表Student
@Data
public class Student {
private int id;
private String name;
private String address;
private Date age;
private int delFlag;
}
- student相关的mapper
// 继承BaseMapper<Student> 有一大堆单表查询方法
@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
- 为springboot添加mapper扫描
// 选择自己的地址
@MapperScan("com.example.mybatisplus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
⑤ 测试
// 注入mapper调用方法
@Autowired
private StudentMapper mapper;
@Test
void contextLoads() {
List<Student> studentList = mapper.selectList(null);
studentList.forEach(System.out::println);
}
第二部分 mapper、service
虽然mybatis-plus
提供给我们很多的方法,但是这是单表,所以我们就需要地自定义方法
自定义方法和mybatis一样,使用mapper.xml映射文件
1.自定义mapper方法
① 在mapper接口中添加自定义方法
List<Student> list();
② 为自己的mapper接口添加映射文件mapper.xml
我在resources下创建mapper包
在mapper下创建StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--mapper命名空间,一定要指定到我们的mapper接口-->
<mapper namespace="com.example.mybatisplus.mapper.StudentMapper">
<!--对应方法-->
<select id="list" resultType="com.example.mybatisplus.entity.Student">
SELECT * FROM student;
</select>
</mapper>
③ 配置mapper.xml文件位置
在yml中配置
因为默认就是resources/mapper/**/*.xml 所以可以不用写
#mybatis-plus配置
mybatis-plus:
configuration:
#mapper.xml映射文件路径 这是默认路径,可以不写
mapper-locations: classpath*:/mapper/**/*.xml
④ 测试
List<Student> studentList = mapper.list();
studentList.forEach(System.out::println);
2. service
在实际开发中我们不会直接去调用mapper,而是调用service去完成业务逻辑
所以mybatis-plus也给我们提供了一套通用的service单表查询操作
① 编写service继承ServiceImpl
编写Studentservice-StudentServiceImpl
继承ServiceImpl<StudentMapper,Student,即可,第一个参数是我们对应的mapper接口,第二个参数是实体类
service类中会自动引入baseMapper,就是我们自定义的mapper
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService {
@Override
public List<Student> list() {
return list(null);
//return baseMapper.list();
}
}
第三部分 常用注解
1. @TableName
用来标注一个实体类对应的表
// 代表我Student对应的表为s_student
@TableName("s_student")
public class Student {
private Long id;
private String name;
private String address;
private Date age;
private int delFlag;
public Student(String name, String address, Date age) {
this.name = name;
this.address = address;
this.age = age;
}
}
全局配置表前缀
mybatis-plus:
global-config:
db-config:
table-prefix: "s_"/'s_'/s_(三种方法都可以)
2. @TableId
用来标注这个字段是主键,并且可以指定主键生成策略
属性
- value:指定该字段映射数据库表哪一个列
- type:指定主键生成策略
默认情况下是雪花算法:当你没有给插入的数据指定id,并且你的主键数据类型为Long时,会随机生成一个20为长度的数作为id
当我们把type指定为IdType.AUTO时,不再使用雪花算法,而是根据你数据库中最大的id自增(前提是数据库表id得设定自增)
@TableName("s_student")
public class Student {
@TableId(value = "u_id",type = IdType.AUTO)
private Long id;
private String name;
private String address;
private Date age;
private int delFlag;
public Student(String name, String address, Date age) {
this.name = name;
this.address = address;
this.age = age;
}
}
全局设置生成策略
mybatis-plus:
global-config:
db-config:
id-type: auto
3. @TableField
映射字段,就是指定该字段对应表中哪列
@TableField(value = "n_name")
private String name;
4. @TableLogic
标注该字段为逻辑删除标记
@TableLogic
private int delFlag;
添加逻辑删除之后,我们做删除不会真正删除而是将字段delFlag的值改为1
查询的时候会自动添加 where del_flag = 0 语句(自定义方法不添加这条语句,还需自己指定)
5. @DS
用来标注一个方法或是一个类中的所有方法用哪个数据源
使用时需要配置多数据源,会在第七部分讲述到
@Override
@DS("data2")
public List<Student> list2() {
return baseMapper.selectList(null);
}
第四部分 条件构造器
当我们使用mybatis提供给我们的方法时,大多数情况需要给一个Query也就是条件构造器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkudaUyc-1684416896952)(…\图片\mybatis-plus-wapper.png)]
有很多实现类,我们可以根据情况进行不同的选择
1.wrapper的一些特性
例子以:QueryWrapper<T>为例
① wrapper中有很多方法
我们可以根据自己的需求,灵活的组合条件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJKzYvG3-1684416896953)(…\图片\MyBatis-plus-queryWrapper.png)]
② and-lambda
当我们现在有这样一个需求
// 获取年龄大于0 并且姓名或者地址中带有‘林’的数据 一定要注意条件优先级
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.lt("age",new Date())
.and(i->i.like("n_name","林").or().like("address","林")); // 当我们使用and时 其中的方法优先执行
List<Student> students = mapper.selectList(wrapper);
System.out.println(students);
③ select
当我们只想获取某些字段的时候就可以使用select方法
// 获取年龄大于0并且姓名或者地址中带有林的数据
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.lt("age",new Date())
.and(i->i.like("n_name","林").or().like("address","林"))
.select("n_name","address");
List<Map<String, Object>> maps = mapper.selectMaps(wrapper);
System.out.println(maps); // 要注意返回值是一个 List<Map<String,Object>>
④ 动态条件
我们可以给我们要拼接的条件指定 是否拼接
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.lt(StringUtils.isBlank(age),"age",new Date()) // 第一个参数我们可以放一个判断,如果为true就拼接条件,如果为false就不拼接
⑤ 方法引用
使用LambdaQueryWrapper可以使用Lambda进而使用方法引用来避免字段写错
LambdaupdateWrapper也可以
LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.ge(StringUtils.isBlank(name),Student::getName,name); // 非常方便
第五部分 插件
配置插件可以强化mybatis-plus的功能
1. 分页插件
① 配置分页插件对象
创建mybatis配置类,将分页拦截器加入到容器中
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
② 测试
创建一个page对象,使用mybatis提供给我们的方法测试分页插件是否添加成功
// 别导错包了 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
Page<Student> page = new Page<>(1,3);
System.out.println(mapper.selectPage(page, null));
// 数据总页数
page.getPages();
// 当前页码
page.getCurrent();
// 数据条数
page.getSize();
// 总数据数
page.getTotal();
// 查到的数据列表
page.getRecords();
// 运行成功就是配置成功了,也可以观察sql
③ 自定义分页方法
自定义分页方法,对我们方法构造有要求
// 方法返回参数必须是page对象,第一个参数必须是page对象 多个参数时需要使用 @Param注解,来标志参数
Page<Student> page(@Param("page")Page<Student> page,@Param("condition") Student req);
实现mapper方法
<select id="page" resultType="com.example.mybatisplus.entity.Student">
SELECT * FROM student
</select>
可以看到,我们并没有实现分页方法,mybatis会自动帮我们实现
2. 乐观锁配置
需要配合数据库使用,数据库中要有一个Vesion字段来同步数据
第一步在对应属性上添加乐观锁注解,使用的时候会自动将该字段 +1 一般视为版本
此后对数据进行增删改操作时,version即会作为查询条件(判断版本是否一致)也会作为参数(判断)
@Version
Integer version;
第二步完善配置乐观锁对象
直接使用MyBatis-puls提供的乐观锁对象
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
3. 日期自动填充
第一步:为需要自动填充的字段添加注解
@TableField(fill = FieldFill.INSERT) // 插入时添加
private Date gmtCreate;
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入更新时添加
private Date gmtModified;
第二步:配置填充插件
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) { //字段插入时填充的数据
metaObject.setValue("gmtCreate",new Date()); //设置那个字段需要自动配置,配置内容是什么
metaObject.setValue("gmtModified",new Date());
}
@Override
public void updateFill(MetaObject metaObject) { //字段更新时插入的数据
metaObject.setValue("gmtModified",new Date());
}
}
第六部分 代码生成器
一键生成与数据库对应的 entity controller service mapper 超级方便!!!,当然需要配置
1.导入依赖
<!--mybatis-plus启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--velocity模板引擎一-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!--代码生成器依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
<scope>test</scope>
</dependency>
<!--MySQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.11</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2.编写代码生成器类
直接 CV,内部一些代码需要根据自己的情况进行配置
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
public class CodeGenerator {
public static void main(String[] args) {
/*
* 代码生成器 需要多个配置
* 1.全局配置 GolbalConfig
* 2.数据源配置 DataSourceConfig
* 3.包路径配置 PackageConfig
* 4.自定义配置 InjectionConfig 根据需要自己配置
* 需要一个 FileOutConfig
* 5.模板配置 TemplateConfig 注意自己使用的模板引擎
* 6.策略配置 strategyConfig
*
* 使用需要修改的配置 全局路径 数据源 包路径 策略配置的表配置
*/
String moduleName = "edu";//用来拼接包名,当前模块名
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
// 生成路径
gc.setOutputDir("E:/JavaCode/Online-Education/education-parent/service/service-edu/src/main/java");
gc.setAuthor("llz");
gc.setOpen(false); //生成后是否打开资源管理器
// gc.setFileOverride(true); //重新生成时文件是否覆盖
gc.setServiceName("%sService");//默认Service接口会使用I开头,去掉首字母I
gc.setIdType(IdType.ASSIGN_ID); //主键策略 使用雪花算法
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型使用java.util.Date
gc.setSwagger2(true);//开启Swagger2模式:自动生成swagger注解
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/education?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);//数据库类型
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(moduleName); //模块名
pc.setParent("com.llz.service");
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(moduleName + "_");//设置表前缀不生成
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setInclude("cms_ad","cms_ad_type");// 设置 自动生成的表名 不指定则生成全部
strategy.setLogicDeleteFieldName("is_deleted");//逻辑删除字段名
strategy.setEntityBooleanColumnRemoveIsPrefix(true);//去掉布尔值的is_前缀
//自动填充
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategy.setTableFillList(tableFills);
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
//设置BaseEntity
strategy.setSuperEntityClass("com.llz.service.base.model.BaseEntity");
// 填写BaseEntity中的公共字段
strategy.setSuperEntityColumns("id", "gmt_create", "gmt_modified");
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
第七部分 多数据源配置
有时候我们使用的数据源不止一个,比如一个数据源负责读,一个负责写
1.导入依赖
<!--多数据源依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--mybatis、mysql、springboot相关依赖省略-->
2.配置yml
spring:
datasource:
# 多数据源配置
dynamic:
# 主数据源
primary: data1
# 设置数据源匹配是否严格
# 默认为false:如果没有找到指定的数据源,就会去找主数据源 true:如果没有找到指定的数据源,直接抛异常
strict: false
datasource:
data1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_local?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
data2:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_local2?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
3. 使用@DS(“DataSourceName”)
@DS(“DataSourceName”) 注解用来标注一个类中的所有方法或是一个方法使用那个数据源
加在接口上不生效
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
@Override
@DS("data1")
public List<Student> list1() {
return baseMapper.selectList(null);
}
@Override
@DS("data2")
public List<Student> list2() {
return baseMapper.selectList(null);
}
}
责写
#### 1.导入依赖
```xml
<!--多数据源依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--mybatis、mysql、springboot相关依赖省略-->
2.配置yml
spring:
datasource:
# 多数据源配置
dynamic:
# 主数据源
primary: data1
# 设置数据源匹配是否严格
# 默认为false:如果没有找到指定的数据源,就会去找主数据源 true:如果没有找到指定的数据源,直接抛异常
strict: false
datasource:
data1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_local?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
data2:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_local2?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
3. 使用@DS(“DataSourceName”)
@DS(“DataSourceName”) 注解用来标注一个类中的所有方法或是一个方法使用那个数据源
加在接口上不生效
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
@Override
@DS("data1")
public List<Student> list1() {
return baseMapper.selectList(null);
}
@Override
@DS("data2")
public List<Student> list2() {
return baseMapper.selectList(null);
}
}