从Mybatis到Mybatis-Plus学习

news2024/11/27 14:48:38

从Mybatis到Mybatis-Plus

  • Mybatis的入门
  • Mybatis的配置解析
    • 核心配置文件
    • 分页配置
    • 注解开发
    • mybatis的执行流程
    • 多对一
    • 一对多
    • 动态SQL
    • mybatis 的缓存
  • Mybatis-plus
    • 快速入门
    • mybatis-plus的框架结构图
    • 分页查询和删除
    • 执行SQL分析打印
    • 条件构造器Wrapper
    • 代码生成器

Mybatis的入门

环境,jdk11maven3.8.1mysql8.0

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录。

mybatis3中文文档

导入maven依赖

		<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        
		<dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>

MybatisUtils 获取 从XML中构建 SqlSessionFactory

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

mybatis-config.xml

<?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>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/mao/dao/UserMapper.xml"></mapper>
    </mappers>
</configuration>

UserMapper 也就是UserDao层的接口

public interface UserMapper {
    // 查询全部用户 getUserList
    List<User> getUserlist();
}

编写对应的xml文件,编写sql语句

<?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="com.mao.dao.UserMapper">
    <select id="getUserlist" resultType="com.mao.pojo.User">
        select * from user;
    </select>
</mapper>

测试类

    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserlist();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

存在问题,maven 的资源过滤问题

java.io.IOException: Could not find resource mybatis-config.xml
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)
	at com.mao.utils.MybatisUtils.<clinit>(MybatisUtils.java:18)
	at com.mao.dao.UserDaoTest.test(UserDaoTest.java:14)

在这里插入图片描述
解决问题,就是maven的资源导出问题

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

发现结果,可以正常查询。
在这里插入图片描述
根据id查询用户

接口方法

// 根据id查询用户
    User getUserById(int id);

mapperSQL语句

    <select id="getUserById" parameterType="int" resultType="com.mao.pojo.User">
        select * from user where id = #{id}
    </select>

测试类

    @Test
    public void testById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);
        sqlSession.close();
    }

通过Map集合设置条件查询
接口方法

    User getUserByMap(Map<String,Object> map);

SQL编写

    <select id="getUserByMap" parameterType="map" resultType="com.mao.pojo.User">
        select * from user where id = #{MapId} and name = #{name};
    </select>

测试类

    @Test
    public void getUserByMap(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("MapId",1);
        map.put("name","mao");
        User userByMap = mapper.getUserByMap(map);
        System.out.println(userByMap);
        sqlSession.close();
    }

Mybatis的配置解析

核心配置文件

在这里插入图片描述
自定义db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
username=root
password=123456

mybatis-config.xml中加入db.properties 的属性导入,引入外部配置文件,也可以指定属性导入。优先外部的配置文件。

    <properties resource="db.properties">
        <property name="username" value="root"/>
    </properties>

typeAliases标签指向实体包的别名指向,可以通过注解@Alias("")标记,也可以通过 <typeAlias type="com.mao.pojo.User" alias="User"/>指定实体类的别名。
typeAliases中的package 会将该包下面的所有类的名字开头字母小写作为resultType的传入参数

<?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>

    <properties resource="db.properties">
        <property name="username" value="root"/>
    </properties>

    <typeAliases>
<!--        <typeAlias type="com.mao.pojo.User" alias="User"/>-->
        <package name="com.mao.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/mao/dao/UserMapper.xml"></mapper>
    </mappers>

</configuration>

设置里面的mapUnderscoreToCamelCase,用于驼峰命名的转换

cacheEnabled开启mybatis的缓存

通过class绑定mapper进行注册,接口和mapper配置文件必须同名并且在同一个包下

<mapper class="com.mao.dao.UserMapper"></mapper>

指定包扫描实现注入绑定

<package name="com.mao.dao"/>

实体类和数据库的字段不对应,建立一个resultMap对不同的字段进行映射

    <resultMap id="UserMap" type="com.mao.pojo.User">
        <result column="pwd" property="paswword"></result>
    </resultMap>
    <select id="getUserList" resultMap="UserMap">
        select * from user;
    </select>

开启日志

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

在这里插入图片描述
log4j日志开启

导入依赖

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>

mybatis核心配置文件中开启log4j的配置,

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

log4j.properties 的属性配置文件

### set log levels ###
log4j.rootLogger = DEBUG , C , D , E 

### console ###
log4j.appender.C = org.apache.log4j.ConsoleAppender
log4j.appender.C.Target = System.out
log4j.appender.C.layout = org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

### log file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ../logs/mybatis_study.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = INFO 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

### exception ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = ../logs/mybatis_study_error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = [mybatis_study][%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

###mybatis show sql###
log4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug

log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug

当前类的日志对象

 static Logger logger = Logger.getLogger(UserDaoTest.class);
 

使用

logger.info("进入testTeacher");

在这里插入图片描述

分页配置

UserMapper接口

List<User> getUserByLimit(Map<String,Integer> map);

UserMapper.xml 配置文件的编写

    <resultMap id="UserMap" type="helloUser">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>
    <select id="getUserByLimit" parameterType="map" resultMap="UserMap">
        select * from user limit #{startIndex},#{pageSize};
    </select>

测试类

    @Test
    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<>();
        map.put("startIndex",1);
        map.put("pageSize",3);
        List<User> userList = mapper.getUserByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

RowBounds分页查询,原因SQL 语言自动提供了分页的功能,但是mybatis提供了这个工具类,采用了面向对象编程的思想,但是效率不如SQL语句高。

接口

List<User> getUserByRowBounds();

mapper配置文件

<select id="getUserByRowBounds" resultMap="UserMap">
        select * from user;
    </select>

测试类,传入mapper的配置文件的位置信息

@Test
    public void getUserByRowBounds(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        RowBounds rowBounds = new RowBounds(1, 2);

        List<User> userList = sqlSession.selectList("com.mao.dao.UserMapper.getUserByRowBounds",null,rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

注解开发

通过注解查询,直接在接口定义的方法上,通过注解编写SQL语句,实现功能

@Select("select * from user")
    List<User> getUserByAnnotation();

测试类,直接使用

    @Test
    public void getUserByAnnotation(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserByAnnotation();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

对应的接口文件直接通过注解编写对应的SQL语句,实现对应的功能

    @Select("select * from teacher where id = #{tid}")
    Teacher getTeacher(@Param("tid") int id);

测试方法

    @Test
    public void getTeacher(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        sqlSession.close();
    }

mybatis的执行流程

mybatis 的执行流程,通过Resources加载配置文件,SqlSessionFactoryBuilder的工厂建造者实例化工厂构造器,在工厂构造器中解析XMLConfigBuilder的文件流,在Configuration中的配置信息,在Builder的时候进行sqlSessionFactory的实例化,进行事务管理,创建执行器,创建sqlSession的对象,实现基本的CRUD,查看是否成功,进行事务的提交或者回滚,最后关闭连接

在这里插入图片描述

多对一

<?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>

    <properties resource="db.properties">
        <property name="username" value="root"/>
    </properties>

<!--    <settings>-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--    </settings>-->

<!--    <typeAlias type="com.mao.pojo.User" alias="User"/>-->

    <typeAliases>
        <package name="com.mao.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
<!--     only one   <mapper resource="com/mao/dao/UserMapper.xml"></mapper>-->
        <mapper class="com.mao.dao.UserMapper"></mapper>
        <mapper class="com.mao.dao.TeacherMapper"></mapper>
        <mapper class="com.mao.dao.StudentMapper"></mapper>
    </mappers>
    
</configuration>

两个表

CREATE TABLE `student` (
  `id` int NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  `pwd` varchar(25) NOT NULL,
  `tid` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;


CREATE TABLE `teacher` (
  `id` int NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

UserMapper.xml 在学生的配置文件实现多对一

通过子查询进行查询

多个学生有同一个老师

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private int id;
    private String name;
    // 学生需要关联以老师 n : 1 associate
    private Teacher teacher;
    // 1: n  collection  一个老师 有多个学生
    private int tid;
}

查询所有的学生信息,根据学生的tid,找到对应的老师

public List<Student> getStudent();

mapper配置文件的编写

    <select id="getTeacher2" resultType="Teacher">
        select * from teacher where id = #{id};
    </select>

    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
<!--        复杂查询根据tid查询到teacher-->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher2"/>
    </resultMap>

    <select id="getStudent" resultMap="StudentTeacher">
        select * from student;
    </select>

测试方法

    @Test
    public void testStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudent();
        for (Student student : studentList) {
            System.out.println(student);
        }
        sqlSession.close();
    }

按照结果嵌套处理,对字段取别名的单行sql解决

接口方法

public List<Student> getStudent2();

mapper的映射文件

    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"></result>
        </association>
    </resultMap>

    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid = t.id;
    </select>

测试方法

    @Test
    public void testStudent2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudent2();
        for (Student student : studentList) {
            System.out.println(student);
        }
        sqlSession.close();
    }

在这里插入图片描述

一对多

TeacherMapper.xml在老师的mapper的配置文件中实现一对多

一个老师对应多个学生

分析,需要在教师的实体类中加入一个学生集合的属性,学生具有老师的tid

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private int id;
    private String name;
    // 老师  一对多
    private List<Student> students;
}

相关子查询

接口方法

Teacher getTeacher4(@Param("tid") int id);

mapper配置文件

    <select id="getTeacher4" resultMap="TeacherStudent2">
        select * from teacher where id = #{tid};
    </select>

    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
    </resultMap>

    <select id="getStudentByTeacherId" resultType="Student">
        select * from student where tid = #{tid};
    </select>

测试方法

    @Test
    public void getTeacher3(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher3(2);
        System.out.println(teacher);
        sqlSession.close();
    }

关联查询,一行SQL进行解决

接口方法

Teacher getTeacher3(@Param("tid") int id);

mapper的配置文件

    <select id="getTeacher3" resultMap="TeacherStudent">
        select s.id sid, s.name sname, t.name tname,t.id tid
        from student s, teacher t
        where s.tid = t.id and t.id = #{tid};
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"></result>
        <result property="name" column="tname"></result>

        <collection property="students" ofType="Student">
            <result property="id" column="sid"></result>
            <result property="name" column="sname"></result>
            <result property="tid" column="tid"></result>
        </collection>
    </resultMap>

测试方法

    @Test
    public void getTeacher4(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher4(1);
        System.out.println(teacher);
        sqlSession.close();
    }

动态SQL

动态sql就是根据不同的条件生成不同的sql语句

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

建立数据库表

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT '博客id',
  `title` varchar(100) NOT NULL COMMENT '博客标题',
  `author` varchar(30) NOT NULL COMMENT '作者',
  `create_time` datetime NOT NULL COMMENT '创作时间',
  `views` int NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mybatis配置标准日志输出,开启下划线的驼峰命名转换,不然日期输出为null

	<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

实体类,通过lombok的插件快速简单的生成有参无参构造,tostringgetset方法

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

IdUtils 的工具类,实现id的随机生成UUID,并且简化随机id

public class IdUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    @Test
    public void testId(){
        System.out.println(IdUtils.getId());
    }
}

增加博客,接口方法

int addBlog(Blog blog);

mapper配置文件

    <insert id="addBlog" parameterType="blog">
        insert into blog(id,title,author,create_time,views)
        values (#{id},#{title},#{author},#{createTime},#{views});
    </insert>

测试方法

    @Test
    public void addBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        Blog blog = new Blog();

        blog.setId(IdUtils.getId());
        blog.setTitle("红楼梦");
        blog.setAuthor("曹雪芹");
        blog.setCreateTime(new Date());
        blog.setViews(1000);
        mapper.addBlog(blog);

        blog.setId(IdUtils.getId());
        blog.setTitle("西游记");
        blog.setAuthor("吴承恩");
        blog.setCreateTime(new Date());
        blog.setViews(1234);
        mapper.addBlog(blog);

        blog.setId(IdUtils.getId());
        blog.setTitle("三国演义");
        blog.setAuthor("罗贯中");
        blog.setCreateTime(new Date());
        blog.setViews(4567);
        mapper.addBlog(blog);

        sqlSession.commit();
        sqlSession.close();

    }

if查询博客的接口方法,实现传入参数或者没有参数的传入方式,但是SQL只有一条,实现SQL的动态变化

List<Blog> ifQueryBlog(Map map);

if查询博客的mapper配置文件

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    <select id="ifQueryBlog" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <include refid="if-title-author"></include>
        </where>

        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>

测试方法

    @Test
    public void ifQueryBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();


//        map.put("title","西游记");
        map.put("author","曹雪芹");
        List<Blog> blogs = mapper.ifQueryBlog(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

choose查询接口方法,不想使用所有的条件,而只是想从多个条件中选择一个使用。

List<Blog> ifQueryBlog(Map map);

mapper的配置文件SQL语句

<select id="chooseQueryBlog" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <!--            <if test="title != null">-->
            <!--                and title = #{title}-->
            <!--            </if>-->
            <!--            <if test="author != null">-->
            <!--                and author = #{author}-->
            <!--            </if>-->

            <choose>
                <when test="title != null">
                    title = #{title}
                </when>
                <when test="author != null">
                    and author = #{author}
                </when>
                <otherwise>
                    and views = #{views}
                </otherwise>
            </choose>
        </where>
    </select>

测试方法

    @Test
    public void ChooseQueryBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();


//        map.put("title","西游记");
//        map.put("author","吴承恩");
        map.put("views",1234);
        List<Blog> blogs = mapper.chooseQueryBlog(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

更新博客的接口方法

int updateBlog(Map map);

编写对应的mapper的配置文件

    <update id="updateBlog" parameterType="map">
        update blog
            <set>
                <if test="title != null">
                    title = #{title},
                </if>
                <if test="author != null">
                    author = #{author}
                </if>
            </set>
        where id = #{id}
    </update>

测试方法

    @Test
    public void updateBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();

//        map.put("title","xiao黄书");
        map.put("author","毛文星");
        //map.put("views",1111);
        map.put("id","f9f530f3ccc34ccbaf8e96493bbce727");
        mapper.updateBlog(map);
        sqlSession.commit();

        sqlSession.close();
    }

foreach遍历查询接口方法,对集合进行遍历(尤其是在构建 IN 条件语句的时候)。查询多个id的时候进行返回,ids是一个集合,可以通过map再次封装,进行查询

List<Blog> foreachQueryBlog(Map map);

对应的mapper的配置文件

<select id="foreachQueryBlog" parameterType="map" resultType="blog">
    select * from blog
<where>
    <foreach collection="ids" item="id" open="and (" close=")" separator="or">
        id = #{id}
    </foreach>
</where>

</select>

测试方法

    @Test
    public void foreachQueryBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(3);
        map.put("ids",ids);
        List<Blog> blogs = mapper.foreachQueryBlog(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

在这里插入图片描述

mybatis 的缓存

MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。

默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:

<cache/>

缓存使用的效果

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用LRU算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

缓存只作用于 cache 标签所在的映射文件中的语句。如果你混合使用Java APIXML 映射文件,在共用接口中的语句将不会被默认缓存。你需要使用 @CacheNamespaceRef 注解指定缓存作用域。

缓存策略

public interface Cache {
    String getId();

    void putObject(Object var1, Object var2);

    Object getObject(Object var1);

    Object removeObject(Object var1);

    void clear();

    int getSize();

    default ReadWriteLock getReadWriteLock() {
        return null;
    }
}

在这里插入图片描述
开启缓存

<?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="com.mao.dao.UserMapper">
    <cache
            eviction="FIFO"
            flushInterval="60000"
            size="512"
            readOnly="true"/>
</mapper>

一级缓存就是本地缓存,与数据库同一次会话期间查询到的数据存放到本地缓存中。以后如果需要获取相同的数据,直接从缓存中获取,不需要走数据库了。只在一次的sqlSession中有效,就是获取到连接到关闭连接的期间有效

由于一级缓存的作用域太低了,所以诞生了二级缓存,二级缓存也就叫做全局缓存。是namespace级别的缓存,一个名称空间,对应一个二级缓存。

  • 一条会话查询一条数据,这个数据就放入到会话的一级缓存中
  • 会话关闭,一级缓存就消失了,但是一级缓存就会保存到二级缓存中
  • 新的会话信息就会从二级缓存中获取内容
  • 不同的mapper文件查出的数据会存放在自己对应的缓存中

Mybatis-plus

官网地址 Mybatis-plus
在这里插入图片描述
优点

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大-部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
    内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

引入 Spring Boot Starter 父工程

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.4</version>
        <relativePath/>
    </parent>

引入其他的依赖

    <dependencies>
        <!--spring-boot-starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--spring-boot-starter-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <!--druid数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
    </dependencies>

配置文件配置端口,数据库连接和连接池

server:
  port: 80

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/ems?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimeZone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

编写dao层的接口

@Mapper
public interface UserDao extends BaseMapper<User> {

}

测试方法

@SpringBootTest
@RunWith(SpringRunner.class)
public class SampleTest {
    @Autowired
    private UserDao userDao;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userDao.selectList(null);
        userList.forEach(System.out::println);
    }
}

出现空指针异常,是因为在测试的类上加上@RunWith(SpringRunner.class)注解即可

java.lang.NullPointerException
	at com.mao.test.SampleTest.testSelect(SampleTest.java:28)

测试插入

    @Test
    public void testinsert() {
        System.out.println(("----- insert method test ------"));
        User user = new User();
        user.setId(6);
        user.setName("coffeemao");
        user.setAge(18);
        user.setEmail("2750@qq.com");
        int count = userDao.insert(user);
        System.out.println(count);
    }

插入成功

在这里插入图片描述
mybatis-plus配置日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

思考,因为自己并没有编写sql语句,没有编写dao对应的xml文件,为什么可以查出数据呢?
因为自己编写的Dao接口继承了BaseMapper<T>在这个接口内部编写好了很多的方法

	int insert(T var1); // 插入

	int deleteById(Serializable var1); // 根据id删除

    int deleteByMap(@Param("cm") Map<String, Object> var1);  // 根据传入的map删除

    int delete(@Param("ew") Wrapper<T> var1);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> var1);

    int updateById(@Param("et") T var1);

    int update(@Param("et") T var1, @Param("ew") Wrapper<T> var2);

    T selectById(Serializable var1);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> var1);

    List<T> selectByMap(@Param("cm") Map<String, Object> var1);

    T selectOne(@Param("ew") Wrapper<T> var1);

    Integer selectCount(@Param("ew") Wrapper<T> var1);

    List<T> selectList(@Param("ew") Wrapper<T> var1);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> var1);

    List<Object> selectObjs(@Param("ew") Wrapper<T> var1);

    IPage<T> selectPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);

    IPage<Map<String, Object>> selectMapsPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);

id的自动生成

https://www.cnblogs.com/haoxinyue/p/5208136.html

数据库插入的id默认值,全局唯一id,默认的ID_WORK

主键自增策略,mybatis-plus使用的是雪花算法
UUID,自增id

nowflakeTwitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。雪花算法支持的TPS可以达到419万左右

mybatis-plus包下的主键自增类型
使用

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.ID_WORKER)
    private Integer id;
    private String name;
    private Integer age;
    private String email;
}

注意导入到mybatis-plus的依赖是

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

源码

package com.baomidou.mybatisplus.annotation;

public enum IdType {
    AUTO(0),// 主键自增
    NONE(1),// 不使用
    INPUT(2),// 输入
    ID_WORKER(3), // 默认的方式
    UUID(4),// 全局唯一标识符
    ID_WORKER_STR(5); // ID_WORKER变为字符串

    private int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}

如果导入的是

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

默认的属性也就不同了,因此还是要看版本信息以及源码

package com.baomidou.mybatisplus.annotation;

public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}

配置

@SpringBootApplication
@MapperScan("com.mao.test.dao")
public class TestApplicaton {
    public static void main(String[] args) {
        SpringApplication.run(TestApplicaton.class,args);
    }
}

注解
@TableName
描述:表名注解,标识实体类对应的表
使用位置:实体类
@TableId
描述:主键注解
使用位置:实体类主键字段
@TableField
描述:字段注解(非主键)
@Version
描述:乐观锁注解、标记 @Version 在字段上

@TableName("user")
public class User {
    @TableId(type = IdType.ID_WORKER)
    private Integer id;
    private String name;
    private Integer age;
    private String email;
}

更新操作,实现根据id进行更新,自动更新,动态SQL

    @Test
    public void testUpdate() {
        System.out.println(("----- update method test ------"));
        User user = new User();
        user.setId(6);
        user.setName("coffeemao");
        user.setAge(20);
        user.setEmail("123456@qq.com");
        int count = userDao.updateById(user);
        System.out.println(count);
    }

sql的拼接
在这里插入图片描述
数据库级别的日期自动填充

CREATE TABLE `user` (
  `id` bigint NOT NULL COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '邮箱',
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

修改之后,达到预期,实现创建时候获取日期,修改时候更新日期,但是这些都是基于数据库的表的操作,在实际开发情况中,不允许对数据库表进行修改,因此,需要引入代码级别的更新时间信息。
在这里插入图片描述

代码级别对时间信息进行无侵入的加入

实体类

@TableName("user")
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;
}

编写处理区进行注解的处理

@Slf4j
@Component
public class MetaDataHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ......");
        this.setFieldValByName("gmtCreate",new Date(),metaObject);
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ......");
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }
}

再次测试发现成功

批量查询

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userDao.selectBatchIds(Arrays.asList(1,2,3));
        userList.forEach(System.out::println);
    }

在这里插入图片描述
加入版本信息的字段,并且修改实体类,版本信息乐观锁的基本实现。

@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;
    @Version
    private Integer version;
}

编写mybatis-plus的配置文件,注入到IOC容器中

@MapperScan("com.mao.test.dao")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
	/**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    /**
     * 新版
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

测试类 ,测试情况是正确的时候,版本信息正确修改

    @Test
    public void testUpdate() {
        System.out.println(("----- update method test ------"));
        User user = new User();
        user.setId(6);
        user.setName("张三");
        user.setAge(20);
        user.setEmail("123456@qq.com");
        int count = userDao.updateById(user);
        System.out.println(count);
    }

并发情况下,出现的情况,A线程对2号用户进行修改,但是没有提交进行修改,B线程也对2号用户进行了修改,进行了修改,直接进行了提交,再对A进程的修改信息进行了提交,结果A进程的提交没有成功

    @Test
    public void testVersion() {
        User user = userDao.selectById(2);
        user.setName("李四");
        user.setAge(20);
        user.setEmail("987654@qq.com");

        // 还没有修改,插队操作
        User user1 = userDao.selectById(2);
        user1.setName("王五");
        user1.setAge(18);
        user1.setEmail("000000@qq.com");
        userDao.updateById(user1);

        userDao.updateById(user);
    }

在这里插入图片描述
查询有同过id的集合进行查询,指定id进行查询,通过Map进行封装属性按照条件进行查询等等
在这里插入图片描述

mybatis-plus的框架结构图

在这里插入图片描述

分页查询和删除

添加分页插件

@MapperScan("com.mao.test.dao")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 添加乐观锁
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        //添加分页
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        
        return mybatisPlusInterceptor;
    }
}

使用page分页对象,进行测试

    @Test
    public void testSelect() {
        Page<User> page = new Page<>(1,3);
        userDao.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
    }

在这里插入图片描述
删除6号用户

    @Test
    public void testdelete() {
        int count = userDao.deleteById(6);
        System.out.println(count);
    }

逻辑删除,添加逻辑删除的字段,deleted,其中0表示未删除,1表示已删除

数据库添加,实体类添加,配置文件修改

在这里插入图片描述
实体类添加字段信息

    @TableLogic
    private Integer deleted;

mybatis-plus配置,0表示未删除,1表示已经删除

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-field: flag
      logic-delete-value: 1
      logic-not-delete-value: 0

测试

    @Test
    public void testdelete() {
        int count = userDao.deleteById(5);
        System.out.println(count);
    }

在这里插入图片描述
查询全部,发现查询出来的都是逻辑未删除的用户
在这里插入图片描述

执行SQL分析打印

在开发过程中遇到的慢sql。进行测试! druid,
作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间
MyBatisPlus也提供性能分析插件,如果超过这个时间就停止运行!

导入依赖

        <!-- p6spy 依赖引入 -->
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>3.9.1</version>
        </dependency>

application.yml

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:p6spy:mysql://localhost:3306/ems?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimeZone=GMT%2B8
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

spy.properties 配置

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

测试方法

    @Test
    public void testSelect() {
        List<User> userList = userDao.selectList(null);
        userList.forEach(System.out::println);
    }

在这里插入图片描述

条件构造器Wrapper

复杂的条件查询,查询name属性不为nullemail属性不为nullage属性大于等于21

    @Test
    public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")
                        .isNotNull("email")
                                .ge("age",21);
        userDao.selectList(wrapper).forEach(System.out::println);
    }

在这里插入图片描述
查找姓名为Tom

    @Test
    public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","Tom");
        userDao.selectList(wrapper).forEach(System.out::println);
    }

在这里插入图片描述
查找年龄区间在2025的用户

    @Test
    public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,25);   
        userDao.selectList(wrapper).forEach(System.out::println);
    }

使用自定义的sql语句进行查询

    @Test
    public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where id<3");
        userDao.selectList(wrapper).forEach(System.out::println);
    }

在这里插入图片描述

代码生成器

导入依赖

		<!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!-- 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>
        <!-- swagger-annotations -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.2</version>
        </dependency>
        <!-- p6spy 依赖引入 -->
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>3.9.1</version>
        </dependency>

编写自动生成代码生成器

public class MybatisAtuoCode {
    public static void main(String[] args) {
        // 需要构建一个 代码自动生成器 对象
        AutoGenerator mpg = new AutoGenerator();
        // 配置策略
        // 1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath+"/src/main/java");
        gc.setAuthor("coffeemao");
        gc.setOpen(false);
        gc.setFileOverride(false); // 是否覆盖
        gc.setServiceName("%sService"); // 去Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);
        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/ems?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);
        //3、包的配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("test");
        pc.setParent("com.mao");
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);
        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        // 设置要映射的表名
        strategy.setInclude("user");
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true); // 自动lombok;
        strategy.setLogicDeleteFieldName("deleted");
        // 自动填充配置
        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.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);
        //执行
        mpg.execute();
    }
}

在这里插入图片描述
但是mybatis-plus的版本更新到3.5.2,此时发生了很多的变化
首先导入的依赖是最新版本的

<!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--模板引擎-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <!-- swagger-annotations -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.2</version>
        </dependency>

编写的自动的代码生成器

public class MybatisAtuoCode {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/ems?&characterEncoding=utf-8&userSSL=false", "root", "123456")
                .globalConfig(builder -> {//全局配置
                    builder.author("coffeemao") // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .disableOpenDir()
                            .outputDir(System.getProperty("user.dir")+"/src/main/java"); // 指定输出目录
                })
                .packageConfig(builder -> {//包配置
                    builder.parent("com.mao") // 设置父包名
                            .moduleName("test") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml,System.getProperty("user.dir")+"/src/main/resources/mybatis/mapper"));// 设置mapperXml生成路径

                })
                .strategyConfig(builder -> {//策略配置
                    builder.addInclude("user"); // 设置需要生成的表名
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker 引擎模板,默认的是Velocity引擎模板
                .execute();

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85827.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

io复用函数的使用

目录 一、概念 二、使用 1.select系统调用 代码实现 前言&#xff1a; 一般多客户端在和服务器通信时&#xff0c;服务器在执行recv时会先阻塞&#xff0c;然后按照顺序依次处理客户端&#xff0c;无论客户端有无数据都会被处理&#xff0c;这样大大降低了执行效率。此时就引…

代理 模式

代理模式 Proxy Pattern 为其他对象提供一个代理以控制对这个对象的访问 可以详细控制访问某个&#xff08;某类&#xff09;对象的方法&#xff0c;在调用这个方法前做前置处理&#xff0c;调用这个方法后做后置处理。 静态代理 直接写死的代码的代理逻辑 动态代理 动态…

12.2、后渗透测试--令牌窃取

攻击机kali&#xff1a;192.168.11.106靶机windows server 2008 R2&#xff1a;192.168.11.134&#xff08;包含ms17_010漏洞&#xff09;一、令牌简介与原理 令牌(Token) 就是系统的临时密钥&#xff0c;相当于账户名和密码&#xff0c;用来决定是否允许这次请求和判断这次请求…

二进制搭建k8s——部署node节点

上篇&#xff1a;二进制搭建k8s——部署etcd集群和单master 二进制搭建k8s——部署node节点二进制搭建k8s——部署node节点环境部署node节点部署网络组件方法一&#xff1a;部署Flannel方法二&#xff1a;部署 CalicoCNI网络插件介绍Kubernetes的三种网络K8S 中 Pod 网络通信&a…

浅浅讲解下Linux内存管理之CMA

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 Contiguous Memory Allocator, CMA&#xff0c;连续内存分配器&#xff0c;用于分配连续的大块内存。CMA…

c语言内存和文件处理有关知识

内存 分配内存的函数calloc&#xff0c;malloc 定义于头文件 <stdlib.h>功能malloc分配内存(函数)calloc分配并清零内存(函数)realloc扩充之前分配的内存块(函数)free归还还之前分配的内存(函数)aligned_alloc(C11)分配对齐的内存(函数) 函数原型 void *malloc(unsigne…

Java基础之Collection的ArrayList

Java基础之Collection的ArrayList一、add()与addAll()二、remove()三、trimToSize()1、案例一、add()与addAll() 跟C 的vector不同&#xff0c;ArrayList没有push_back()方法&#xff0c;对应的方法是add(E e)&#xff0c;ArrayList也没有insert()方法&#xff0c;对应的方法是…

Oracle---初学篇

Oracle初学篇 Oracle的启动&#xff0c;监听&#xff0c;用户 文章目录Oracle初学篇Oracle的启动Oracle的监听监听服务的主要文件1.listener.ora2.tnsnames.ora3.sqlnet.oraOracle用户Oracle安装成功后默认的三个用户创建用户Oracle的启动 之前写了关于如何在CentOS7上搭建Ora…

2021年全国研究生数学建模竞赛华为杯D题抗乳腺癌候选药物的优化建模求解全过程文档及程序

2021年全国研究生数学建模竞赛华为杯 D题 抗乳腺癌候选药物的优化建模 原题再现&#xff1a; 一、背景介绍   乳腺癌是目前世界上最常见&#xff0c;致死率较高的癌症之一。乳腺癌的发展与雌激素受体密切相关&#xff0c;有研究发现&#xff0c;雌激素受体α亚型&#xff0…

LeetCode 0547. 省份数量:图的连通分量

【LetMeFly】547.省份数量 力扣题目链接&#xff1a;https://leetcode.cn/problems/number-of-provinces/ 有 n 个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a 与城市 b 直接相连&#xff0c;且城市 b 与城市 c 直接相连&#xff0c;那么城市 a …

Windows文件夹开启大小写敏感

Windows 的文件系统的文件名&#xff0c;是大小写不敏感的&#xff0c;也就是你的文件名是 a.txt 或者 A.txt&#xff0c;在 Windows 中都是一视同仁&#xff0c;认为是同一个文件。 自从 Windows 10 引入 Linux 子系统&#xff08;WSL&#xff09;后&#xff0c;有越来越多开…

JAVA毕业设计——基于ssm的汽车租赁管理系统 (源代码+数据库)

代码地址 https://github.com/ynwynw/carRental-public 毕业设计所有选题地址 https://github.com/ynwynw/allProject 基于Springboot的汽车租赁管理系统 (源代码数据库)601 一、系统介绍 汽车租赁系统总共分为两个大的模块&#xff0c;分别是系统模块和业务模块。其中系统模…

基于混沌原子搜索优化的电力系统(HPS)负载频率自动控制(ALFC)(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

Spring Security 中的四种权限控制方式

Spring Security 中对于权限控制默认已经提供了很多了&#xff0c;但是&#xff0c;一个优秀的框架必须具备良好的扩展性&#xff0c;恰好&#xff0c;Spring Security 的扩展性就非常棒&#xff0c;我们既可以使用 Spring Security 提供的方式做授权&#xff0c;也可以自定义授…

如何实现外网访问API接口

Application Programming Interface 缩写为API&#xff0c;中文翻译为“应用程序接口”&#xff0c;是一些预先定义的函数&#xff0c;或指软件系统不同组成部分衔接的约定。目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源码&…

TVS管开关电源防护应用及电源防护元件的品类

瞬态抑制二极管简称TVS管。其作用原理是能够在极短的时间内承受反向电压的冲击&#xff0c;使得两极之间的电压钳位在特定电压水平上&#xff0c;有效避免了对后面电路的冲击&#xff0c;从而保护了被保护电子线路中的精密元件不受其损害。 瞬态抑制二极管TVS的钳位响应速度为为…

pytest + yaml 框架 -7.用例分层机制

前言 当我们测试流程类的接口&#xff0c;需反复去调用同一个接口&#xff0c;就会想到复用API&#xff0c;在代码里面可以写成函数去调用。 那么在yaml 文件中&#xff0c;我们可以把单个API写到一个yaml 文件&#xff0c;测试用例去调用导入API。 pip 安装插件 pip instal…

电子产品设计的流程有哪些

电子产品设计过程是指导工业外观设计的具体环节&#xff0c;主要包括产品市场需求分析、产品设计、产品原型设计、生产测试设计、大规模生产等方法和步骤。 一、电子产品设计流程是什么? 1.产品市场需求分析是电子产品设计成功的第一步&#xff0c;也是非常重要的一步。开发者…

JavaSE(数组)

1. 数组 数组创建及初始化 总结&#xff1a; 三种写法包括了动态初始化和静态初始化&#xff0c;其中省略格式不能再省略&#xff08;拆分&#xff09;&#xff1b;没有初始化时&#xff08;默认值为基类类型对应的默认值&#xff09;其中引用类型的默认值为null 三种写法 1…

RK3288-8.1-添加一个人体感应的开关-pir_pin_status

收到一个人体感应的需求,在设置添加一个开关 第一步,确定人体感应接口的GPIO 可知GPIO7_B5为对应GPIO 第二步,注册对应DTS 然后去驱动内注册对应的节点 很基础的东西,就不多说了,省略一万字......................(得到节点) cat sys/devices/platform/attr/pir_pin_status …