MyBatis

4 篇文章 0 订阅
3 篇文章 0 订阅

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. 调通配置,能从数据库获取到数据
1.步骤
  1. 创建maven工程,导入mybatis以及数据库相关依赖
  2. 编写与数据库表对应的实体类
  3. 编写一个实体类对应的mapper.xml(也就是我们的sql)
  4. 编写mybatis配置文件 mybatis-config.xml
  5. 编写测试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中

缓存失效

  1. 进行 **增删改 **操作,会清除清除一级
  2. 调用sqlsession执行不同的sql语句
  3. 执行clearCache()方法,清除缓存
  4. 调用不同的sqlsession方法,缓存不会生效
2. 二级缓存

二级缓存作用域是SqlSessionFactory,默认并没有开启

如何开启二级缓存?

  1. 在mybatis配置文件中开启缓存,默认开始,不用配置
<settings>
     <setting name="cacheEnabled" value="true"/>
</settings>
  1. 在需要开启缓存的mapper.xml中添加,<cache/>标签
<mapper namespace="com.llz.mapper.StudentMapper">
    <cache/>
    ...
</mapper>
  1. 最关键的一步,sqlSession必须关闭或提交数据才能保存到SqlSessionFactory中

缓存失效

  1. 进行 **增删改 **操作,会清除清除二级缓存

第五部分 追源码

(待完成)

1. new SqlSessionFactoryBuilder().build()
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

解析xml标签内容

① properties

读取配置文件

② settings
③ typeAliases
  1. 先判断子节点是package在判断是否是typeAlias
  2. 如果是package,进行包扫描,获取.class结尾的文件,通过类加载器,创建出对应的class文件,判断该class是否有Alias注解,没有的话,使用alias.toLowerCase(Locale.ENGLISH),将type的首字母转为小写,放入TypeAliasRegistry.Map<String, Class<?>> typeAliases中
④ environments
⑤ mappers
  1. 判断子节点优先级 package>resource>url>class
  2. 如果是package那么会扫描包得到所有文件,获取.class结尾的文件,通过类加载器,创建出对应的class文件,通过type创建MapperProxyFactory,

MyBatis-Plus

在mybatis的基础上做了功能增强

第一部分 hello mybatis-plus

1. 实现步骤
  1. 创建spring boot 项目,导入相关依赖
  2. 在yml文件中配置 数据库配置
  3. 创建entity、mapper、添加扫描
  4. 测试
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
  1. 实体类对应数据表Student
@Data
public class Student {
    private int id;
    private String name;
    private String address;
    private Date age;
    private int delFlag;
}
  1. student相关的mapper
// 继承BaseMapper<Student> 有一大堆单表查询方法
@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
  1. 为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

用来标注这个字段是主键,并且可以指定主键生成策略

属性

  1. value:指定该字段映射数据库表哪一个列
  2. 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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值