MyBatis框架

Top:MyBatis框架

https://mybatis.net.cn/参考文档

mybatis 是一个持久层框架

主要用于来对数据库进行操作

mybtais 底层还是对jdbc的封装

mybatis是一个 ORM 映射的框架

O ==> 对象
R ==> 数据库表
M ==> 映射
mybatis 能够实现数据库表(列)对象(属性)映射关系

一、Mybatis 的优势

  1. 相对于传统的jdbc来进行开发,代码量少了百分之五十
  2. 它是一个orm映射框架,能够实现数据库表与对应的映射
  3. mybatis 框架支持动态sql语句,提供了一些动态的标签
  4. mybatis 轻量级,操作起来比较简单
  5. mybatis 框架实现sql与代码分离,便于后台代码的扩展与维护

二、MyBatis框架的前期搭建

(一) idea中 mybatis插件安装

在plugins -> 下载MyBatisX插件 -> 勾选使用

(二)idea中xml模板创建

在setting -> File and Code Template -> Files -> +

请添加图片描述

1. 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">
 
2. Config的约束
<?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">

(三)数据库配置文件引入

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/数据库名称?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root

三、MyBatis正式搭建

1.新建数据库 新建表
2.创建项目导入响应的依赖(jar)
3.新建一个实体Bean
4.编写核心配置文件编写mapper映射关系的配置文件

(二) 核心jar包

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>${mybatis.version}</version>
</dependency>

(四)核心配置文件

  • 给实体类自定义命名
  • 配置多个环境
  • el 引入数据库(数据源)
  • 映射文件的关联方式
<?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="jdbcConfig.properties"/>
    
    <typeAliases>
<!--   给实体类自定义命名   -->
<!--单个的来设置别名-->     
<!--        < type="com.qf.entity.UsertypeAlias" alias="user"/>-->
<!--包下所有实体类设置别名  别名默认是首字母小写 user-->
        <package name="com.qf.entity"/>
        
    </typeAliases>
    
<!--    配置多个环境-->
    <environments default="mysql">
<!--        配置mysql环境-->
        <environment id="mysql">
<!--            事务管理器-->
            <transactionManager type="JDBC"/>
<!--            数据源-->
            <dataSource type="POOLED">
<!--                当配置好数据库的properties属性后,可以通过  el表达式来获取配置文件的信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
<!--    映射文件的关联方式-->
<!--        通过文件类路径引入映射文件-->
        <mapper resource="com/qf/mapper/UserMapper.xml" />
<!--        用类注册引入映射器接口(一般注解的时候使用)-->
<!--        <mapper class="com.qf.mapper.UserMapper"/>-->
<!--        通过包名引入映射器接口(一般注解的时候使用)-->
<!--        <package name="com.qf.mapper"/>-->
        
        <mapper resource="com/qf/mapper/AdminMapper.xml" />
        <mapper resource="com/qf/mapper/StudentMapper.xml" />
    </mappers>
</configuration>
1. 核心配置文件xml目录结构

请添加图片描述

2. MybatisConfig.xml具体解释

POOLED and UNPOOLED

1.environments  ==>表示环境的配置  可以配置多个环境
2.environment id="mysql" 指定是mysql的环境
3.transactionManager  配置事务管理器
4.type 
  JDBC:表示使用jdbc 的方式来进行事务的管理
  MANAGED:没有做任何操作 依赖于容器  以容器的方式的来进行事务管理
           spring +mybatis  ==设置参数MANAGED   表示已容器spring的方式来进行事务的管理
5.dataSource ==>数据源
   POOLED ==> 表示一连接池的方式来管理连接   不会反复的创建与销毁连接
   UNPOOLED ==> 不是以连接池的方式来进行管理连接  使用的时候都创建连接与销毁连接
   JNDI==>必须在web环境,依赖于web容器 在tomcat 中可以进行配置(重点)

(五)mapper映射关系的配置文件

1.namespace  ==>命名空间  完整的包名+类名
2.<select>查询 <insert> 增加 <update> 修改 <delete>删除
3.id==>对应的是mapper方法的名称
4.parameterType==>参数类型
5.resultType==>返回值类型

(六)举例 . 基本的增删改查

(配置UserMapper.xml文件)

<!--
	实体类Bean(User)的全路径:
		com.qf.entity.User
	持久层Dao(UserMapper)的全路径:
		com.qf.mapper.UserMapper
-->
<select id="selectAll" resultType="user">
    select * from user
</select>

<insert id="insertUser" parameterType="user">
    insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>

<update id="updateUserByUid" parameterType="user">
    update user set uname=#{uname},upwd=#{upwd},udate=#{udate} where uid=#{uid}
</update>

<delete id="deleteUserByUid" parameterType="int">
    delete from user where uid=#{uid}
</delete>

<select id="selectUserByUid" parameterType="int" resultType="user">
    select * from user where uid=#{uid}
</select>

(七)举例 . 测试类

package com.qf.test;

import com.qf.entity.User;
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 selectAllTest01() throws IOException {
        //获取mybatis的核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
        //获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //通过工厂对象获取SqlSession
        SqlSession sqlSession = factory.openSession(true);
        //调用方法 执行数据库操作 完整包名+类名+方法名称
        List<User> userList = sqlSession.selectList("com.qf.mapper.UserMapper.selectAll");
        for (User u : userList) {
            System.out.println(u);
        }
    }
    
    //动态代理写法
    public   void selectAllTest02() throws IOException {
        //获取mybatis的核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
        //获取工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //通过工厂对象获取SqlSession
        SqlSession sqlSession = factory.openSession(true);
        //调用方法 执行数据库操作
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.selectAll();
        userList.foreach(user->System.out::Println)
    }
}

四、工具类的抽取

(一)新建一个SqlSessionFactoryUtils工具类

package com.qf.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author:lyz
 * @since: jdk 1.8
 **/
public enum SqlSessionFactoryUtils {
    SSFU;//枚举型
    
    private SqlSessionFactory sqlSessionFactory;
    
    SqlSessionFactoryUtils(){
        //try-catch快捷键捕获:Ctrl+Win+Alt+t
        try {
            InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //定义一个公有的方法返回sqlSessionFactory
    public SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

(二)新建一个CommentMapper

package com.qf.utils;

import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;

/**
 * @author:lyz
 * @since: jdk 1.8
 **/
public class CommentMapper {
    public SqlSession sqlSession;
    
    @Before
    public void before(){
        sqlSession=SqlSessionFactoryUtils.SSFU.getSqlSessionFactory().openSession(true);
    }
    
    @After
    public void after(){
        sqlSession.close();
    }
}

(三)抽取工具类后的测试类(举例)

package com.qf.test;

import com.qf.entity.User;
import com.qf.mapper.UserMapper;
import com.qf.utils.CommentMapper;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author:lyz
 * @since: jdk 1.8
 **/
public class UserMapperTest extends CommentMapper {
//    基础增删改查
    @Test
    public void selectAll() throws IOException {
        List<User> userList = sqlSession.selectList("com.qf.mapper.UserMapper.selectAll");
        for (User u : userList) {
            System.out.println(u);
        }
    }
    @Test
    public void insertUser(){
        User user=new User();
        user.setUname("ccc");
        user.setUpwd("123");
        user.setUdate(LocalDateTime.now());
        int num=sqlSession.insert("com.qf.mapper.UserMapper.insertUser",user);
        System.out.println(num);
    }
    @Test
    public void updateUserByUid(){
        User user=new User();
        user.setUname("test");
        user.setUpwd("test");
        user.setUdate(LocalDateTime.now());
        int num = sqlSession.update("com.qf.mapper.UserMapper.updateUser",user);
        System.out.println(num);
    }
    @Test
    public void deleteUserByUid(){
        int num=sqlSession.delete("com.qf.mapper.UserMapper.deleteUser",6);
        System.out.println(num);
    }
    @Test
    public void selectUserByUid(){
        /*User u = sqlSession.selectOne("com.qf.mapper.UserMapper.selectUserByUid", 1);
        System.out.println(u);*/

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectUserByUid(1);
        System.out.println(user);
    }
}

五、①常见问题

(一)查询的时候传递多参

<!--            查询的时候传递多参-->

<!--方法一:arg0~arg* 依次获取传递进来的参数-->
<!--  直接#{} 如何arg 再根据传递过来的参数顺序获取值(从0开始获取)-->
<select id="selectUserByUidAndUName01" resultType="user">
    select * from user where uid=#{arg0} and uname=#{arg1}
</select>
<!--方法二:使用 map集合-->
<!--  new HashMap(),以键值对的方式存储,在通过键值对的方式获取-->
<!--  其中键可以任意取名,只要获取值的时候对应好就行-->
<select id="selectUserByUidAndUName02" resultType="user">
    select * from  user where uid=#{key0} and uname=#{key1}
</select>
<!--方法三:通过注解-->  <!--建议使用这种-->
<!--  在定义方法的时候就给要传入的参数用 @Param()标记上-->
<!--  然后在@Param("自定义命名的位置")内自定义其传入参数的别名,用于sql语句读取的时候通过别名调用-->
<select id="selectUserByUidAndUName03" resultType="user">
    select * from  user where uid=#{uid} and uname=#{sb}
</select>
<!--方法四:通过对象的属性名(自动查找)-->
<select id="selectUserByUidAndUName04" parameterType="user" resultType="user">
    select * from user where uid=#{uid} and uname=#{uname}
</select>

(二)模糊查询

为了尽可能避免sql注入问题,建议使用concat(…)拼接

<!--            模糊查询-->
<!--方法一:占位符?式插入-->
<select id="selectUserLikeUName01" resultType="com.qf.entity.User">
    select * from user where uname like #{uname}
</select>
<!--方法二:sql拼接式插入(会产生sql注入问题   ==延申出来的问题==》 #{}与${}的区别)-->
<select id="selectUserLikeUName02" resultType="com.qf.entity.User">
    select * from user where uname like '%${uname}%'
</select>
<!--方法三:调用concat(……)方法-->  <!--建议使用这种-->
<select id="selectUserLikeUName03" resultType="com.qf.entity.User">
    select * from user where uname like concat("%",#{uname},"%")
</select>

(三)数据库列名与实体类属性名不一致

myabtis是一个orm映射的框架 数据库的列名对应实体类的属性。如果数据库的列名与实体类的属性对应不上
就获取不到值,这个时候就得用到使用resultMap

1. 数据库列名as实体类属性
2. 调用resultMap
<!--            补充: -->
<!--    resultMap : 用于自定义返回结果集
            id特例必须用 id标签去写
            其他元素用 result去写
          (写的内容为 实体类属性 与 数据库表的列名 用以相互对应)
                    property : 实体类属性
                    column : 数据库表的列名
-->
<!--            数据库列名与实体类属性名不一致的时候,可以在执行语句的时候-->
    
<!--方法一:数据库列名as实体类属性 -->
<!--  给数据库的列名 as为 实体类的属性名-->
<!--  同时给数据库的表,起别名  方便调用其属性值-->
<select id="selectAllAdmin01" resultType="com.qf.entity.Admin">
    select a.aid,a.name as adminName,a.pwd as adminPwd,a.date as dateTime from admin a
</select>
    
<!--方法二:调用resultMap -->   <!--建议使用这种-->
<!--  其中 resultMap中的 id必须式唯一的(用于辨认对应的 resultMap值)-->
<!--  property属性名 column表列名-->
<resultMap id="selectAllAdmin02ResultMap" type="admin">
    <id property="aid" column="aid"></id>
    <result property="adminName" column="name"></result>
    <result property="adminPwd" column="pwd"></result>
    <result property="dateTime" column="date"></result>
</resultMap>
<select id="selectAllAdmin02" resultMap="selectAllAdmin02ResultMap">
    select * from admin a 
</select>
    

(四)主键回填

1. 标签属性解释
keyColumn ==>数据库表中主键的列名
keyProperty==>实体类的属性
resultType ==> 返回值类型
order AFTER/BEFORE 在增加后或者是在增加前执行这个sql语句
select last_insert_id()  ==>表示查询出当前表中 最后的id 值
select replace(UUID(),"-","")  ==>表示查询出当前表中,回填的UUID值,同时将UUID中的"-"换成""
select "???"  ==>表示查询出当前表中,回填的值,同时将其直接更换成为"???"
2.回填int类型

使用场景

​ 在插入数据成功之,需要立即获取查询当前数据的id,但是在数据库中一般都是主键是自增长,这种场景就可以使用主键回填。

​ 例如二阶段的项目 生成订单成功之后 需要动态修改购物车的数据

3.回填String类型
<!--    主键回填一:回填int类型的id-->
<!--			这样能够自增长的id在执行完语句后,会返还到对象中,我们也可以从中调用到。
				如果没进行id的主键回填的话,我们只能获取到id对应的int类型 的默认值0-->
<insert id="insertUser1" parameterType="user">
    <selectKey keyColumn="uid" keyProperty="uid" resultType="int" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>

<!--    主键回填二:回填String类型的uname-->
<!--		select replace(UUID(),"-","")
				在执行sql语句之前,将uname的回填数据更改为UUID(),同时将UUID中的"-"换成""
			select replace("???","niuzi","what")
				在执行sql语句之前,将uname的回填数据更改为"???",同时将其中的"niuzi"换成"what"
			select "???"
				在执行sql语句之前,将uname的回填数据直接更换成为"???"
-->
<insert id="insertUser2" parameterType="user">
    <selectKey keyColumn="uname" keyProperty="uname" resultType="String" order="BEFORE" >
        select "???"
    </selectKey>
    insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>

(五)sql片段

把部分常用的sql语句,提取出来,构建成片段,多次使用。

使用场景:用于sql公共代码的提取 一般用于查询比较多

<!--	sql片段:把部分常用的sql语句提取出来构建成片段多次使用-->
<sql id="userNWD">uname,upwd</sql>
<select id="selectUser3" resultType="com.qf.entity.User">
    select <include refid="userNWD"/> from user
</select>

六、MyBatis处理关联关系-多表连接

实体间的关系:关联关系(拥有 has、属于 belong)

  • OneToOne:一对一关系(Passenger— Passport)

  • OneToMany:一对多关系(Employee — Department)

  • ManyToMany:多对多关系(Student — Subject)

请添加图片描述

(零)Bean的实例

package com.qf.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;
/**
 * @author:lyz
 * @since: jdk 1.8
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int uid;
    private String uname;
    private LocalDateTime ubirthday;
    private String usex;
    
    //一对一 关系映射 (数据库内关系)
    private Card card;
    //一对多 关系映射 (数据库内关系)
    private List<Order> orderList;
    
    //多对多 关系映射 (数据库内关系)
    private List<Role> roleList;
}

(一)普通多表关联

1. 一对一
<!--                一对一             -->
<!--    一对一连接的时候,返回自定义返回结果集 内要附加 association-->
<!--       association “同行内”要填 property(实体类内与该表关联的 关系映射属性是哪一个)
                                   column(通过数据库内该表的那个列名 去进行关系映射)
                      (一对一的要填) javaType(用于说明和那个表相关连)
                      -->
<!--       association “内部”要填 被该表相关连的“javaType外表”
                                 实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectOneByOneMap" type="user">
    <id column="uid" property="uid"/>
    <result column="uname" property="uname"/>
    <result column="ubirthday" property="ubirthday"/>
    <result column="usex" property="usex"/>
    <association property="card" column="uid" javaType="card">
        <id column="cid" property="cid"/>
        <result column="cnumid" property="cnumid"/>
        <result column="uid" property="uid"/>
    </association>
</resultMap>

<select id="selectOneByOne" resultMap="selectOneByOneMap">
    select u.*,c.cnumid from `user` u,card c where u.uid=c.cid
</select>
2. 一对多
<!--                一对多             -->
<!--    一对多连接,返回自定义结果集  内要附加 collection-->
<!--       collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
                                  column(通过数据库内该表的那个列名 去进行关系映射)
                     (一对多的要填) ofType(用于说明和那个表相关连)
                     -->
<!--       collection “内部”要填 被该表相关连的“ofType”
                                实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectOneByManyMap" type="user">
    <id column="uid" property="uid"/>
    <result column="uname" property="uname"/>
    <result column="ubirthday" property="ubirthday"/>
    <result column="usex" property="usex"/>
    <collection property="orderList" column="uid" ofType="order">
        <id column="oid" property="oid"/>
        <result column="oname" property="oname"/>
        <result column="uid" property="uid"/>
    </collection>
</resultMap>

<select id="selectOneByMany" resultMap="selectOneByManyMap">
    select u.*,o.* from `user` u inner join `order` o on u.uid=o.uid
</select>
3. 多对多(need 中间表)
<!--                多对多 (需要借助中间表)             -->
<!--    多对多连接,返回自定义结果集  内要附加 collection-->
<!--       collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
                                  column(通过数据库内该表的那个列名 去进行关系映射)
                     (一对多的要填) ofType(用于说明和那个表相关连)
                     -->
<!--       collection “内部”要填 被该表相关连的“ofType”
                                实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectManyByManyMap" type="user">
    <id column="uid" property="uid"/>
    <result column="uname" property="uname"/>
    <result column="ubirthday" property="ubirthday"/>
    <result column="usex" property="usex"/>
    <collection property="roleList" column="uid" ofType="role">
        <id column="rid" property="rid"/>
        <result column="rname" property="rname"/>
        <result property="rdesc" column="rdesc"/>
    </collection>
</resultMap>

<select id="selectManyByMany" resultMap="selectManyByManyMap">
    select * from `user` u 
    inner join u_r ur on u.uid=ur.uid
    inner join role r on ur.rid=r.rid
</select>

(二)嵌套多表关联

1. 嵌套一对一
<!--                嵌套一对一             -->
<!--    一对一连接,返回自定义结果集  内要附加 association-->
<!--       association “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
                                  column(通过数据库内该表的那个列名 去进行关系映射)
                     (一对一的要填) javaType(用于说明和那个表相关连)
                  (嵌套的需要额外加) select(所嵌套方法的全路径“相当于先执行目前的sql命令,
                                          然后再把column内数据传过去,充当参数,执行下一个sql命令”)
                     -->
<!--       嵌套的话 association “内部”不需要填写内容要填-->
<resultMap id="selectOneByOneQianQianMap" type="user">
    <id property="uid" column="uid"/>
    <result property="uname" column="uname"/>
    <result column="ubirthday" property="ubirthday"/>
    <result column="usex" property="usex"/>
    <association property="card" column="uid" javaType="card" select="com.qf.mapper.CardMapper.selectCardByUid"/>
</resultMap>

<select id="selectOneByOneQian" resultMap="selectOneByOneQianQianMap">
    select * from `user`
</select>


<!--被嵌套的方法-->
<select id="selectCardByUid" parameterType="int" resultType="card">
    select * from card where uid=#{uid}
</select>
2. 嵌套一对多
<!--                嵌套一对多             -->
<!--    一对多连接,返回自定义结果集  内要附加 collection-->
<!--       collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
                                  column(通过数据库内该表的那个列名 去进行关系映射)
                     (一对一的要填) javaType(用于说明和那个表相关连)
                  (嵌套的需要额外加) select(所嵌套方法的全路径“相当于先执行目前的sql命令,
                                          然后再把 column内数据传过去,充当参数,执行下一个sql命令”)
                     -->
<!--       嵌套的话 collection “内部”不需要填写内容要填-->
<resultMap id="selectOneByManyQianMap" type="user">
    <id property="uid" column="uid"/>
    <result property="uname" column="uname"/>
    <result column="ubirthday" property="ubirthday"/>
    <result column="usex" property="usex"/>
    <collection property="orderList" column="uid" ofType="order" select="com.qf.mapper.OrderMapper.selectOrderByUid"/>
</resultMap>

<select id="selectOneByManyQian" resultMap="selectOneByManyQianMap">
    select * from `user`
</select>


<!--被嵌套的方法-->
<select id="selectOrderByUid" parameterType="int" resultType="order">
    select * from `order` o where o.uid=#{uid}
</select>

七、动态SQL

(一)where-if"…"

<!--            where-if"…"    -->
<select id="selectUserByUsexAndUname" resultType="user">
    select * from `user` 
    <where>
        <if test="usex != null and usex !=''">
            and usex like concat("%",#{usex},"%")
        </if>
        <if test="uname != null and uname !=''">
            and uname like concat("%",#{uname},"%")
        </if>
    </where>
</select>

(二)where-choose - (when"…" / otherwise)

<!--            where-choose - (when"…" / otherwise)  -->
<select id="selectUserByUsexAndUname0" resultType="user">
    select * from `user` 
    <where>
        <choose>
            <when test="usex != null and usex !=''">
                and usex like concat("%",#{usex},"%")
            </when>
            <when test="uname != null and uname !=''">
                and uname like concat("%",#{uname},"%")
            </when>
            <otherwise>
                1=1
            </otherwise>
        </choose>
    </where>
</select>

(三)set-if"…"

<!--            set-if"…"        -->
<update id="updateUser" parameterType="user">
    update `user` 
    <set>
        <if test="uname != null and uname !=''">
            uname=#{uname},
        </if>
        <if test="ubirthday != null and ubirthday !=''">
            ubirthday=#{ubirthday},
        </if>
        <if test="usex != null and usex !=''">
            usex=#{usex},
        </if>
    </set>
    where uid=#{uid}
</update>

(四)trim"…“-if”"

<!--            trim"…"-if""     -->     <!--  set-if"…"的进化版  -->
<!--    prefix : 在全部if语句的   前面加上 特定内容-->
<!--    suffix : 在全部if语句的   后面加上 特定内容-->
<!--    prefixOverrides : 在全部if语句的   前面删除 特定内容-->
<!--    suffixOverrides : 在全部if语句的   前面删除 特定内容-->
<update id="updateUser2" parameterType="user">
    update `user`
    <trim prefix="set" suffixOverrides="," suffix="where uid=#{uid}">
        <if test="uname!=null and uname!=''">
            uname=#{uname},
        </if>
        <if test="ubirthday != null and ubirthday !=''">
            ubirthday=#{ubirthday},
        </if>
        <if test="usex != null and usex !=''">
            usex=#{usex},
        </if>
    </trim>
</update>

(五)foreach

1. 多条同时修改
2. 插入方式为Map的时候
<!--            foreach     -->
<!--    
        collection 容器类型 : list、array、map
        open 起始符   eg  (
        close 结束符   eg  )
        separator 分隔符   eg  ,
        index 下标号 从0开始,依次递增
        item 当前项 任意名称(循环中通过 #{任意名称} 表达式访问)
-->
<insert id="insertManyUser" parameterType="list">
    insert into `user`(uname,ubirthday,usex) values 
    <foreach collection="list" separator="," close=";" item="u">
        (#{u.uname},#{u.ubirthday},#{u.usex})
    </foreach>
</insert>

<insert id="deleteManyUser" parameterType="list">
    delete from `user` where uid in 
    <foreach collection="list" open="(" separator="," close=")" item="uid">
        #{uid}
    </foreach>
</insert>


<!--    多条同时修改-->
<insert id="updateManyUser" parameterType="list">
    update `user`
    <trim prefix="set" suffixOverrides=",">
        <trim prefix="uid = case " suffix="end,">
            <foreach collection="list" item="u">
                when uid=#{u.uid} then #{u.uid}
            </foreach>
        </trim>
        <trim prefix="uname = case " suffix="end,">
            <foreach collection="list" item="u">
                when uid=#{u.uid} then #{u.uname}
            </foreach>
        </trim>
    </trim>
    where
    <foreach collection="list" item="u" separator="or">
        uid=#{u.uid}
    </foreach>
</insert>

<select id="selectManyUser" parameterType="list" resultType="user">
    select * from `user` where
    <foreach collection="list" open=" uid in (" close=")" separator="," item="u">
        #{u}
    </foreach>
</select>

<select id="selectManyUser2" resultType="user">
    select * from `user` where
    <foreach collection="array" open=" uid in (" close=")" separator="," item="this">
        #{this}
    </foreach>
</select>

<!--    插入方式为Map的时候,
                其 collection属性值:必须为Map的key值
                        (此处的key值可以自定义,但调用的时候要输入相对应的自定义key名)
                真正要传入用于调用的数据放在value值处
                -->
<select id="selectManyUser3" resultType="user">
    select * from `user` where
    <foreach collection="DiyKey" open="uid in (" close=")" separator="," item="DiyItemName">
        #{DiyItemName}
    </foreach>
</select>

八、Druid连接池

​ Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SQL 解析器组成。该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL 翻译等,程序员可以通过定制来实现自己需要的功能。

(一)配置pom.xml

引入Druid依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>

(二)创建DruidDataSourceFactory

MyDruidDataSourceFactory并继承PooledDataSourceFactory,并替换数据源。

package com.qf.utils;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
/**
 * @author:lyz
 * @since: jdk 1.8
 **/
public class MyDruidDataSourceFactory  extends PooledDataSourceFactory {
    public MyDruidDataSourceFactory(){
        //替换数据源
        this.dataSource = new DruidDataSource();
    }
}

(三)修改mybatisConfig.xml

mybatisConfig.xml中连接池相关配置。

<!--    配置数据库-->
<environments default="mysql">
    <environment id="mysql">
        <transactionManager type="JDBC"/>

        <!--<dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>-->

        <!--更改数据源后,必须按照其特定的 “命名规范name” 来配置相关的配置文件-->
        <dataSource type="com.qf.utils.MyDruidDataSourceFactory"><!--数据源工厂-->
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>

    </environment>
</environments>

九、缓存(Cache)

内存中的一块存储空间,服务于某个应用程序,旨在将频繁读取的数据临时保存在内存中,便于二次快速访问。

使用场景:1.数据量比较小

​ 2.数据需要经常使用,不会经常发生改变

​ 3.数据不是特别准确的时候

无缓存:用户在访问相同数据时,需要发起多次对数据库的直接访问,导致产生大量IO、读写硬盘的操作,效率低下
请添加图片描述
有缓存:首次访问时,查询数据库,将数据存储到缓存中;再次访问时,直接访问缓存,减少IO、硬盘读写次数、提高效率
请添加图片描述

(一)一级缓存

SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。

注意:无需任何配置,默认开启一级缓存

1. sqlSession.clearCache(); 
	//清空全部数据 
	/*清空 (当前SqlSession连接的一级缓存) 的全部数据*/

2. sqlSession.commit();
	//提交同时清空全部数据
	/*提交 (当前SqlSession连接的一级缓存) ,
	 同时默认 (当前SqlSession连接的一级缓存) 清空全部数据*/
/*
*   缓存:使用情况
*       1.数据量小
*       2.经常使用,但不经常改变
*       3.数据不是特别准确的时候
* 
*   一级缓存:
*       1.存取的是对象
*       2.只能用于查询
*       3.增删改会自动提交,然后清空一级缓存内数据
* 
* */

(二)二级缓存

SqlSessionFactory级别的缓存,同一个SqlSessionFactory构建的SqlSession发起的多次同构查询,会将数据保存在二级缓存中。

/*
*   二级缓存:
*       当没有 commit时(结束一级缓存),
*       会自动继续调用,一级缓存内的对象
* 
*       [ 当中间 commit(提交) 清空一级缓存内对象数据时,
*           会通过 Mapper接口(命名空间) 找到对应的二级缓存中获取值,
*           然后再次调用后,也只会从二级缓存中查找 ]
* 
*  */
1. 配置二级缓存
(1). 修改mybatisConfig.xml
<!--    开启二级缓存-->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

<!--在<typeAliases>标签的上边加上<settings>配置,该工程可以开启二级缓存-->
(2). 修改 对应Bean的Mapper.xml配置文件
<!--    开启二级缓存的开关-->
<cache/>

具体的查询语句使用二级缓存
(3). 具体的查询语句使用二级缓存
<!--    针对于具体的查询语句使用二级缓存-->
<select id="selectUserByUidCache" parameterType="int" resultType="user" useCache="true">
    select * from `user` u where u.uid=#{uid}
</select>

<!--特定语句内加入 useCache="true" 表示该方法启动二级缓存-->
2. 举例 . 一级缓存
//    一级缓存只能用于查询功能
@Test//实验一级缓存
public void selectUserByUidTest01() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(true);//自动提交是:当程序全部结束后,才提交(而不是方法结束后提交)
    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper1.selectUserByUid(4);//第一次查询后,会将查询获得的对象存储到一级缓存中

    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    User user2 = userMapper2.selectUserByUid(4);//没有提交的时候,再次查询,会直接从一级缓存中 查询相应的对象

    System.out.println(user1==user2);//true
    sqlSession.commit();
}

@Test//实验一级缓存
public void selectUserByUidTest02() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper1.selectUserByUid(4);

    //提交:   提交后自动清空一级缓存内数据
    sqlSession.commit();

    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    User user2 = userMapper2.selectUserByUid(4);

    System.out.println(user1==user2);//false
    sqlSession.commit();
}

@Test//实验一级缓存
public void insertUserTest01() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper1.selectUserByUid(4);

    User user = new User();
    user.setUname("神威超人");
    user.setUbirthday(LocalDateTime.now());
    user.setUsex("男");
    int i = userMapper1.insertUser(user);//执行增(删改)操作后:会自动提交数据到数据库,同时自动清空一级缓存内数据

    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    User user2 = userMapper2.selectUserByUid(4);

    System.out.println(user1==user2);//false
    sqlSession.commit();
}
3. 举例 . 二级缓存
@Test//实验二级缓存
public void selectUserByUidCache() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper1.selectUserByUidCache(4);

    sqlSession.commit();

    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    User user2 = userMapper2.selectUserByUidCache(4);
    UserMapper userMapper3 = sqlSession.getMapper(UserMapper.class);
    User user3 = userMapper3.selectUserByUidCache(4);

    System.out.println(user1==user2);//false , 由于中间 清空一级缓存中的对象数据,所以user1调的是一级缓存的对象数据 user2调用的二级缓存的数据值,所以不是同一对象故==返回值为false
    System.out.println(user2==user3);//false , 由于二级缓存存储的是数据值,而==比较引用类型的是地址(是否同一对象),故返回为false
    System.out.println(user2.equals(user3));//true , 因为此时两次调用的都是二级缓存中的值,equals比较的也是值,所以返回为true
    sqlSession.commit();
}

十、延迟加载(懒加载)

延迟加载:懒加载 ==>谁用谁加载 不是立即进行加载,使用的时候才进行加载【单例设置模式

使用场景
需求:实现登录功能 => 用户表 ==> 订单表 (一对多的关系)
产生这种场景:使用嵌套查询 在进行登录的时候 会将订单的信息查询出来,
登录的时候 没有必须查询出订单信息,在使用订单表的数据的时候 再查询订单的信息(懒加载)

​ 立即加载:一对一的关系的时候会使用
​ 懒加载:一对多的关系的时候使用懒加载

(一)嵌套一对一的懒加载

1. 修改 对应Bean的Mapper.xml配置文件
<!--    嵌套一对一懒加载-->
<resultMap id="selectOneToOneQianMap" type="user">
    <id property="uid" column="uid"/>
    <result property="uname" column="uname"/>
    <result property="ubirthday" column="ubirthday"/>
    <result property="usex" column="usex"/>
    <association property="card" column="uid" javaType="card"
                 select="com.qf.mapper.CardMapper.selectCardByUid" fetchType="lazy" />
</resultMap>
<select id="selectOneToOneQian" resultMap="selectOneToOneQianMap">
    select  * from `user`
</select>

<!--在 "嵌套一对一" 的基础上,给association加上一个 fetchType="lazy" 属性-->
2. 测试 用到其数据的时候才会执行sql语句
//    嵌套一对一的懒加载
@Test
public void selectOneToOneQian() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.selectOneToOneQian();
    userList.forEach(user -> {
        System.out.println(user.getUname());
        if (user.getCard()!=null){
            System.out.println(user.getCard().getCnumid());
        }
    });
}

(二)嵌套一对多的懒加载

1. 修改 对应Bean的Mapper.xml配置文件
<!--    嵌套一对多懒加载-->
<resultMap id="selectOneToManyQianMap" type="user">
    <id property="uid" column="uid"/>
    <result property="uname" column="uname"/>
    <result property="ubirthday" column="ubirthday"/>
    <result property="usex" column="usex"/>
    <collection property="orderList" column="uid" ofType="list"
                select="com.qf.mapper.OrderMapper.selectOrderByUid" fetchType="lazy"/>
</resultMap>
<select id="selectOneToManyQian" resultMap="selectOneToManyQianMap">
    select * from `user`
</select>

<!--在 "嵌套一对多" 的基础上,collection fetchType="lazy" 属性-->
  1. 测试 用到其数据的时候才会执行sql语句
//    嵌套一对多的懒加载
@Test
public void selectOneToManyQian() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.selectOneToManyQian();
    userList.forEach(user -> {
        System.out.println(user.getUname());
        List<Order> orderList = user.getOrderList();
        if (orderList.size()>0){
            orderList.forEach(order -> System.out.println(order));
        }
    });
}

十一、PageHelper(分页插件)

PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。

  • 访问与下载
    • 官方网站:https://pagehelper.github.io/
    • 下载地址:https://github.com/pagehelper/Mybatis-PageHelper
  • 开发步骤
    • PageHelper中提供了多个分页操作的静态方法入口。

(一)配置

1. 修改pom.xml 引入依赖

引入依赖pom.xml中引入PageHelper依赖。

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>${pagehelper.version}</version>
</dependency>

2.修改mybatisConfig.xml
<!--    配置PackHelper分页插件-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

<!--在<typeAliases>标签的下方,加上<plugins>配置,该工程使用…插件-->

(二)测试分页插件PageHelper

//    测试分页插件PageHelper
@Test
public void selectAllUserTestPageHelper() throws IOException {
    InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    SqlSession sqlSession = factory.openSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
/*
*   设置分页:
*       第一个参数:pageNum:当前页
*       第二个参数:pageSize:每页展示最大数
*/
    PageHelper.startPage(1,3);

    List<User> userList = userMapper.selectAllUserTestPaPageHelper();

    /*  实例化PageInfo  同时把要分页展示的数据传入  */
    PageInfo<User> pageInfo=new PageInfo<>(userList);
    System.out.println(pageInfo.toString());
}

(三)常用的PageInfo

属性名描述
pageNum当前页
pageSize页量
total总记录数
pages总页数
list集合(数据)

(四)注意事项

十二、MyBatis注解操作

通过在接口中直接添加MyBatis注解,完成CRUD。

(一)修改mybatisConfig.xml

<mappers>
    <!--<mapper resource="com/qf/mapper/UserMapper.xml"/>
        <mapper resource="com/qf/mapper/CardMapper.xml"/>
        <mapper resource="com/qf/mapper/OrderMapper.xml"/>-->
    <package name="com.qf.mapper"/>
</mappers>

<!--使用<package>方式直接将工程下包内,的全部持久层接口类都配置号映射关系-->
<!--也可以用<mapper class="……">  和package一样的效果-->

(二)测试

  • 持久层接口类 - 模版

    package com.qf.mapper;
    
    import com.qf.entity.Card;
    import com.qf.entity.User;
    import org.apache.ibatis.annotations.*;
    import org.apache.ibatis.mapping.FetchType;
    
    import java.util.List;
    /**
     * @author:lyz
     * @since: jdk 1.8
     **/
    public interface UserMapper {
        //………………
    }
    
  • 测试类

    package com.qf.test;
    
    import com.qf.entity.User;
    import com.qf.mapper.UserMapper;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.time.LocalDateTime;
    import java.util.List;
    /**
     * @author:lyz
     * @since: jdk 1.8
     **/
    public class MyTest {
        private SqlSession sqlSession = null;
    
        public SqlSession getSqlSession() {
            if (sqlSession == null) {
                try {
                    sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatisConfig.xml")).openSession(true);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return sqlSession;
        }
    }
    
1. 简单的增删改查
(1). 持久层接口类
@Insert("insert into `user` (uname,ubirthday,usex)values(#{uname},#{ubirthday},#{usex})")
int insertUser(User user);

@Delete("delete from `user` where uid=#{uid}")
int deleteUserByUid(@Param("uid")int uid);

@Update("update `user` set uname=#{uname},ubirthday=#{ubirthday},usex=#{usex} where uid=#{uid}")
int updateUserByUid(User user);

@Select("select * from `user` where uid=#{uid}")
User selectUserByUid(@Param("uid")int uid);
(2). 测试类
@Test
public void insertUser() {
    User user = new User();
    user.setUname("TempInsert");
    user.setUbirthday(LocalDateTime.now());
    user.setUsex("男");
    int i = getSqlSession().getMapper(UserMapper.class).insertUser(user);
    System.out.println(i);
}

@Test
public void deleteUserByUid() {
    int i = getSqlSession().getMapper(UserMapper.class).deleteUserByUid(12);
    System.out.println(i);
}

@Test
public void updateUserByUid() {
    User user = new User();
    user.setUid(14);
    user.setUname("TempUpdate");
    user.setUbirthday(LocalDateTime.now());
    user.setUsex("女");
    int i = getSqlSession().getMapper(UserMapper.class).updateUserByUid(user);
    System.out.println(i);
}

@Test
public void selectUserByUid() {
    User user = getSqlSession().getMapper(UserMapper.class).selectUserByUid(14);
    System.out.println(user);
}
2. 嵌套一对一
(1). 持久层接口类
/*  嵌套一对一
      1.(最后一个)连接的 @Result 配置内容:
       1.1. property 实体类中用于嵌套的属性名
       1.2. column   在数据库中两个表,是关于那个列名相关联起来的
       1.3. javaType 返回的数据类型
                (tips:若返回为数组则是List.class类型,
                        若返回为其他实体类则是 实体类.class)
       1.4. one   要配置 @One
           1.4.1 @One 必须配置 select="" 
                           填被嵌套方法的全路径 eg: com.qf.mapper.CardMapper.selectByUid
                      选择性配置 fetchType= 
                           加载模式(默认/懒加载/立即加载)eg:FetchType.LAZY(懒加载)
 */
@Select("select * from `user`")
@Results({
    @Result(id=true,property = "uid",column = "uid"),
    @Result(property = "uname",column = "uname"),
    @Result(property = "ubirthday",column = "ubirthday"),
    @Result(property = "usex",column = "usex"),
    @Result(property = "card",column = "uid",javaType = Card.class,
            one = @One(
                select = "com.qf.mapper.CardMapper.selectByUid",fetchType = FetchType.LAZY
            ))
})
List<User> selectOneToOneQian();
(2). 测试类
@Test
public void selectOneToOneQian() {
    List<User> userList = getSqlSession().getMapper(UserMapper.class).selectOneToOneQian();
    userList.forEach(user -> {
        System.out.println(user.getUname());
        if (user.getCard()!=null){
            System.out.println(user.getCard().getCnumid());
        }
    });
}
3. 嵌套一对多
(1). 持久层接口类
/*  嵌套一对多
      1.(最后一个)连接的 @Result 配置内容:
       1.1. property 实体类中用于嵌套的属性名
       1.2. column   在数据库中两个表,是关于那个列名相关联起来的
       1.3. javaType 返回的数据类型
                (tips:若返回为数组则是List.class类型,
                        若返回为其他实体类则是 实体类.class)
       1.4. many   要配置 @Many
            1.4.1 @Many 必须配置 select="" 
                            填被嵌套方法的全路径 eg: com.qf.mapper.CardMapper.selectByUid
                        选择性配置 fetchType= 
                            加载模式(默认/懒加载/立即加载)eg:FetchType.LAZY(懒加载)
*/
@Select("select * from `user`")
@Results({
    @Result(id = true,property = "uid",column = "uid"),
    @Result(property = "uname",column = "uname"),
    @Result(property = "ubirthday",column = "ubirthday"),
    @Result(property = "usex",column = "usex"),
    @Result(property = "orderList",column = "uid",javaType = List.class,
            many = @Many(
                select = "com.qf.mapper.OrderMapper.selectOrderByUid",fetchType = FetchType.LAZY
            ))
})
List<User> selectOneToManyQian();
(2). 测试类
@Test
public void selectOneToManyQian() {
    List<User> userList = getSqlSession().getMapper(UserMapper.class).selectOneToManyQian();
    userList.forEach(user -> {
        System.out.println(user.getUname());
        if (user.getOrderList().size()>0){
            user.getOrderList().forEach(order -> {
                System.out.println(order.getOname());
            });
        }
    });
}

十三、MyBatis的逆向工程

自动生成数据库中“表”的“实体类”,及简单的“增删改查”功能

(一)配置

1. 修改mybatisConfig.xml
<!--    配置 MyBatis的逆向工程 依赖包-->
<properties>
    <mybatis.version>3.5.6</mybatis.version>
    <mysql-connector-java.version>8.0.17</mysql-connector-java.version>
    <mybatis-generator-maven-plugin.version>1.3.2</mybatis-generator-maven-plugin.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql-connector-java.version}</version>
    </dependency>
</dependencies>

<!--    配置 MyBatis的逆向工程 插件-->
<build>
    <plugins>

        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>${mybatis-generator-maven-plugin.version}</version>
            <configuration>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
            </configuration>
        </plugin>
        <!--这里其实可配置多个插件,eg:PackHelper分页插件-->
        <!--<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>-->
    </plugins>
</build>

<!--在<typeAliases>标签的下方,加上<plugins>配置,该工程使用…插件-->
2. 添加配置文件generator.properties
  • jdbc.driverLocation = 本地mysql-connector-java-****.jar 的全路径
  • jdbc.driverClass = com.mysql.cj.jdbc.Driver(版本8以上)
    • com.mysql.jdbc.Driver(版本8以下)
  • jdbc.connectionURL = jdbc:mysql:///数据库名称?serverTimezone=Asia/Shanghai(版本8以上)
    • jdbc:mysql://localhost:3306/数据库名称(版本8以下)
    • 不写localhost:3306 默认本地service
  • jdbc.userId = mysql用户名
  • jdbc.password = mysql密码
jdbc.driverLocation=C:\\Users\\lyz\\.m2\\repository\\mysql\\mysql-connector-java\\8.0.17\\mysql-connector-java-8.0.17.jar
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.connectionURL=jdbc:mysql:///mybatis_03?serverTimezone=Asia/Shanghai
jdbc.userId=root
jdbc.password=root
3. 添加配置文件 generatorConfig.xml
  • javaModelGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径

  • sqlMapGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径

  • javaClientGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径

  • 添加要生成数据库中的表单,的特定配置信息

    • tableName :数据库中表单的名称
    • domainObjectName :该表单生成的实体类名称
    <table tableName="user" domainObjectName="User"
           enableCountByExample="false" enableUpdateByExample="false"
           enableDeleteByExample="false" enableSelectByExample="false"
           selectByExampleQueryId="false">
    </table>
    
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--导入属性配置-->
    <properties resource="generator.properties"></properties>

    <!--指定特定数据库的jdbc驱动jar包的位置-->
    <classPathEntry location="${jdbc.driverLocation}"/>

    <context id="default" targetRuntime="MyBatis3">

        <!-- optional,旨在创建class时,对注释进行控制 -->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--jdbc的数据库连接 -->
        <!--Mysql版本8 以上的要而外配置<property name="nullCatalogMeansCurrent" value="true"/>
		   Mysql版本8 以下的则不需要这条属性-->
        <jdbcConnection
                        driverClass="${jdbc.driverClass}"
                        connectionURL="${jdbc.connectionURL}"
                        userId="${jdbc.userId}"
                        password="${jdbc.password}">
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>


        <!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>


        <!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
            targetPackage     指定生成的model生成所在的包名
            targetProject     指定在该项目下所在的路径
        -->
        <javaModelGenerator targetPackage="com.qf.entity"
                            targetProject="src/main/java">

            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对model添加 构造函数 -->
            <property name="constructorBased" value="true"/>
            <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
            <property name="trimStrings" value="true"/>
            <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>

        <!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
        <sqlMapGenerator targetPackage="com.qf.mapper"
                         targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
                type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
                type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
                type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
        -->
        <javaClientGenerator targetPackage="com.qf.mapper"
                             targetProject="src/main/java" type="XMLMAPPER">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>


        <table tableName="user" domainObjectName="User"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false">
        </table>

        <table tableName="card" domainObjectName="Card"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false">
        </table>

        
    </context>
</generatorConfiguration>
4. 配置插件 mybatis-generator:generate

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值