MyBatis基础设置

目录

设置自己mybatis库:

​编辑

​编辑

插件

基础插件(必)

分页:

实体类基础构造

数据库

单元测试(必)

整体:

mybatis-config.xml引入(规定引入的前后)

添加修改删除跟查询:

引包-pom.xml

创建实体类

在resources中写入一个mybatis-config.xml文件

测试

mybatis-connfig.xml的一些配置

映射文件

模糊查询

添加时获取递增的主键值

起别名·

对于多参传递方法(@param

如果列名跟属性名不一致的情况

一对一

一对多

include使用:

动态标签

forach

choose when

trim

set

一级缓存

应用场景(一级&含义)

开启条件(一级)

失效条件(一级)

一级缓存失效代码示例(后续二级缓存所使用的数据表一致)

二级缓存

应用场景(二级&含义)

开启条件(二级)

失效条件(二级)

整合第三方缓存EHCach

四.Mybatis一二级缓存开启顺序

分页

mapper类中的@中注解使用


设置自己mybatis库:

插件

pom.xml:

基础插件(必)
<dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
分页:
https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
        </dependency>
实体类基础构造
  <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

实体类中的使用

@Date  //get、set方法

@NoArgsConstructor  //无参

@AllArgsConstructor  //全部属性有参方法
数据库
  <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
单元测试(必)
   <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
整体:

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>


<!--    分页-->
    <plugins>
        <!--设置分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

数据库

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/1010_db?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

引入

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <!--name是固定的 value根据需要配置为自己的内容-->
            <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/java009/mapper/OrderMapper.xml"/>-->
        <package name="com.java009.mapper"/>
    </mappers>

配置文件执行流程

添加修改删除跟查询:

引包-pom.xml
<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>

<!--        //构造-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>
创建实体类

com.zz.entity

//添加注释
@Data
//没有构造方法
@NoArgsConstructor
//有构造方法
@AllArgsConstructor

创建mapper包--写实体类接口

写入业务层查询,修改,插入,删除

//查询
List<Student> listAll();

//插入
int insert (Student student);

//删除
int delete(int id);

//修改
int update(Student student);

对应的resources中创建跟实体类接口一样的路径跟名字

sql语句:

<!-- 查-->
    <select id="listAll" resultType="com.zz.entity.Student">
        select *from t_student;
    </select>

<!--    插-->
    <insert id="insert" parameterType="com.zz.entity.Student">
        insert into t_student
        values (null,#{name},#{phone},#{email},#{profession},#{age});
    </insert>

<!--    //改-->
    <update id="update" >
        update  t_student    set name=#{name},phone=#{phone},email=#{email},profession=#{profession},age=#{age} where id=#{id}
    </update>

<!--删-->
    <delete id="delete" >
        delete from t_student where id=#{id}
    </delete>
在resources中写入一个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">
                <!--name是固定的 value根据需要配置为自己的内容-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/00520_db" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>

测试

总节

//加载mybatis主配置文件
InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory对
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
//通过会话工厂,创建sql会话对象
SqlSession session=factory.openSession();
//通过session获取mapper对象
StudentMapper studentMapper=session.getMapper(StudentMapper.class);

//通过mapper接口对象完成插入
Student s=new Student(null,"帅","123","309QQ.com","软件技术",13);
//插入
int add=studentMapper.insert(s);
System.out.println("插入记录"+add);
//提交代码
session.commit();
//关闭会话

//b.通过接口对象进行查询
List<Student> students = studentMapper.listAll();
System.out.println(students);
//5.关闭会话
session.close();

修改

Student student=new Student(25,"买天奇","15","150@qq.com","体育",30);

        //调用方法
studentMapper.update(student);
//提交
session.commit();
//关闭会话
session.close();

删除

int add=studentMapper.delete(24);
session.commit();
session.close();
mybatis-connfig.xml的一些配置
-    关联配置文件-->
    <properties resource="db.properties"></properties>

<!--    mybatis全文配置-->
    <settings>
    
<!--        配置日志文件-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        
<!--        配置数据库属性下划线变小驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

<!--    配置类型别名-->
    <typeAliases>
        <!--         配置单个实体类的别名 -->
        <!--         <typeAlias type="com.java009.entity.Emp" alias="emp"/> -->
        <!--         使用包配置的方式,批量配置该包下的所有实体类别名 -->
        <package name="com.java009.entity"/>
    </typeAliases>

映射文件

<mappers>
    <!--        关联mapper文件,获取针对表的增删改查配置-->
    <!--        <mapper resource="com/java009/mapper/EmpMapper.xml"/>-->

    <!--        通过配置Mapper接口类,与Mapper文件进行映射-->
    <!--        <mapper class="com.java009.mapper.EmpMapper"/>-->

    <!--        配置mapper接口包,会自动关联映射包中的所有类-->
    <package name="com.java009.mapper"/>
</mappers>

特殊字符

<![CDATA[SQL语句]]

日志:

引入jar包:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</dependency>

2.引入日志属性文件

名称必须为log4j.properties

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

模糊查询

其中有concat(‘&’,key,‘&’)拼接查询

添加时获取递增的主键值

useGenerateKeys:是否使用生成的主键
KeyPoperty:生成后的主键赋给哪个属性

起别名·

单个实体类别名

<typeAliases>
   <typeAlias type="com.zz.entity.Role" alias="R">

多个实体类

  <package name="com.zz.entity"/>

对于多参传递方法(@param

如果列名跟属性名不一致的情况

方法1:

在查询时,进行重命名

方法2:使用resultMap方法重写属性名称

 起别名
       id:标识
       type:执行完查询后返回的数据类型
-->
    <resultMap id="myMap" type="com.zz.entity.Role">
<!--        id:主键标志 proper="属性
            column:"列名"
-->
        <id property="id" column="id"></id>
        <result property="name" column="role_name"></result>
        <result property="code" column="role_code"></result>
        <result property="description" column="description"></result>

    </resultMap>

方法3:

全文配置中设置下划线变为小驼峰

<setting name="mapUnderscoreToCamelCase" value="true"/>

一对一

sql语句

autoMapping:自动映射属性名称,将查询结果映射到Java中

 <resultMap id="stuMap" type="student" autoMapping="true">
        <id property="studentId" column="studentId"/>
        <result property="studentName" column="student_name"/>
        <result property="sex" column="sex"/>

<!--        使用association 进行一对一对象关联映射-->
        <association property="classInfo" javaType="ClassInfo">
            <result property="className" column="class_name"/>
        </association>
    </resultMap>

一对多

//一对多关联学生对象
List<Student> studentList;

测试

public void Sq()throws Exception{
    ClassInfoMapper mapper=session.getMapper(ClassInfoMapper.class);
    List<ClassInfo> c=mapper.listAll();
    for(ClassInfo classInfo:c){
        System.out.println(classInfo);
    }
}

include使用:

因为sql语句的重复性,用<sql id="">标签提取应用

动态标签

if

where

<!--    多表关联查询-->
    <select id="list" parameterType="booksQuery" resultMap="booksMap">
        <include refid="mainQuery"></include>
-- 条件查询
<where>
    <if test="bookName!=null and bookName!=''">
        and book_name like concat('%',#{bookName},'%')
    </if>
    <if test="author!=null and author!=''">
        and auther like concat('%',#{author},'%')
    </if>
    <if test="price">
        and price=#{price}
    </if>
     <if test="pubDateStart!=null">
         and pub_date >=#{pubDateStart}
     </if>
     <if test="pubDateEnd!=null">
         <![CDATA[and pub_date<=#{pubDateEnd}]]>
     </if>
    <if test="category!=null and category.categoryName!=null and category.categoryName!=''">
        and category_name=#{category.categoryName}
    </if>
</where>
    </select>
forach

根据id查询、插入

    <select id="listByLds" resultMap="booksMap">
        <include refid="mainQuery"></include>
 where book_id in
    <foreach collection="list" item="date" open="(" close=")" separator=",">
        #{data}
    </foreach>
    </select>

<!--    插入-->
    <insert id="insertBath">
        insert into tb_books
        (book_name,author,price,pub_date,category_id)
        VALUES
        <foreach collection="list" item="book" separator=",">
            (#{book.bookName},#{book.author},#{book.price},#{book.pubDate},#{book.category.categoryId})
        </foreach>
    </insert>

choose when
    <select id="listByChoose" resultMap="booksMap">
        <include refid="mainQuery"></include>
<!--<trim prefix="where" prefixOverrides="and">-->
        <where>
            <choose>
                <when test="bookName!=null and bookName!=''">
                    and book_name like concat("%",#{bookName},"%")
                </when>
                <when test="author!=null and author!=''">
                    and author =#{author}
                </when>
                <otherwise>
                    and book_id = 1
                </otherwise>
            </choose>
        </where>
<!--&#45;&#45;        </trim>-->
    </select>
trim

set

一级缓存

  缓存是存放数据的地方,即将产生的数据暂时存放到内存中。(缓存就是数据交换的缓冲区(称作Cache),是存贮数据(使用频繁的数据)的临时地方。当用户查询数据,首先在缓存中寻找,如果找到了则直接执行。如果找不到,则去数据库中查找。-大佬的解释)

  • 应用场景(一级&含义)

​ 即通过同一个SqlSession查询出来的数据会被缓存,第二次查询相同的数据的时候会直接从缓存中取数据,不会再去访问数据库再获取数据。

开启条件(一级)

​ Mybatis的一级缓存是默认开启的。

失效条件(一级)

​ 使用不同的SqlSession 两次查询间存在对数据的增删改操作 两次查询的查询条件不一致 手动清空了缓存

一级缓存失效代码示例(后续二级缓存所使用的数据表一致)

下面以查询员工信息为例,即通过员工的id信息查询员工所有的信息(我们通过log4j实现日志功能,来查看查询语句执行的次数,即为访问数据库的次数,需要引入log4j的依赖和文件,可以直接查到)

员工表如下:

    mapper.xml如下:

    我们先看看SqlSession未失效时,Sql语句的执行情况(使用同一个SqlSession获取Mapper代理对象执行方法,查询员工信息
/**

     * 测试一级缓存未失效的情况

     */

    @Test

    public void CacheTestAtFirst(){

        //获取SqlSession对象(这是封装好了的方法,直接获取)

        SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();

//获取Mapper代理对象
    CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
    CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);
 
    //第一次查询员工信息
    List<EmpMapper> empById1 = mapper1.getEmpById(1);
    System.out.println(empById1);
   //第二次查询员工信息
    List<EmpMapper> empById2 = mapper2.getEmpById(1);
    System.out.println(empById2);
 
    //关闭资源
    sqlSession1.close();
 

运行结果如下:

结论:我们通过日志可以看到,我们调用了两次查询员工信息的方法,但日志显示只执行了一次Sql语句,即只访问了一次数据库,因为第二次直接从缓存里拿数据了,这就是Mybatis的一级缓存,下面我们再看看一级缓存失效的情况。

以下为“使用不同的SqlSession".eg(测试类)

​ 测试代码如下:

/**

     * 测试一级缓存,Sqlsession级别-使用不同的SqlSession会导致缓存失效

     */

    @Test

    public void CacheTestByOne(){

        //获取两个SqlSession对象

        SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();

        SqlSession sqlSession2 = SqlSessionUtil.getSqlSession();

CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
 
    //执行Sql
    List<EmpMapper> empById = mapper1.getEmpById(1);
 
    System.out.println(empById);
   CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
    //执行Sql
    List<EmpMapper> empById1 = mapper2.getEmpById(1);
    System.out.println(empById1);
 
    //关闭资源
    sqlSession2.close();
    sqlSession1.close();

运行结果如下:

结论:可以看到,使用不同的SqlSession对象后,日志显示了两次Sql查询语句,即访问了两次数据库,Mybatis的一级缓存失效了。

以下为“手动清空了缓存”.eg

​ 测试代码示例如下:

/**

- 手动清空缓存使得一级缓存失效
  */
  @Test
  public void CacheTestByOneA(){
  SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
 
    List<EmpMapper> empById = mapper1.getEmpById(1);
 
    System.out.println(empById);
 
    //清空缓存
    sqlSession1.clearCache();
    CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);
    List<EmpMapper> empById1 = mapper2.getEmpById(1);
    System.out.println(empById1);
        sqlSession1.close();

运行结果如下:

结论:与第一种失效的情况一致,还有两种条件也会造成Mybatis的一级缓存失效,测试过程类似, 不再一一展示。

二级缓存

应用场景(二级&含义)

​ 和一级缓存的定义相似,即由同一个SqlSessionFactory创建的(不同)SqlSession对象查询的结果会被缓存。

开启条件(二级)

​ 1.在mapper.xml文件中设置<settings>标签,默认是开启的,不需要设置

​ <settings> <setting name="cacheEnabled" value="true"/> settings>

​ 2.在mapper.xml文件设置<cache/>标签

3.查询数据所转换的实体类类型必须转换实现序列化接口

​ 4.必须在SqlSession关闭或提交后,才会开启二级缓存

​ 二级缓存开启成功示例:

​ 测试代码如下:

  @Test

    public void CacheTestByTwo() throws IOException {

        //1.获取核心配置文件

        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

//2.获取Builder,从同一个sqlSessionFactory中获取SqlSession对象
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
 
    SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
    SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
 
    CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
    CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
 
    List<EmpMapper> emp1 = mapper1.getEmpById(1);
    System.out.println(emp1);
 
    //关闭SqlSession
    sqlSession1.close();
 List<EmpMapper> emp2 = mapper2.getEmpById(1);
    System.out.println(emp2);
 
    sqlSession2.close();
    sqlSession1.close();
    }

运行结果如下:

结论:可以看到日志中只执行了一次Sql语句,即两次查询中,只访问了一次数据库(注意Mybatis的缓存查询顺序,先二级再一级,其中显示的命中率Hit Ratio也意味开启了二级缓存)

失效条件(二级)

两次查询之间执行了一次增删改操作SqlSession未关闭,数据被保存在一级缓存中

整合第三方缓存EHCach

​ 即使用第三方缓存来代替Mybatis的二级缓存,这里不详细介绍

四.Mybatis一二级缓存开启顺序

​ 查询数据时,会按照以下顺序获取数据

二级缓存中是否有数据一级缓存中是否有数据查询数据库

理解:Mybatis的二级缓存要比一级缓存作用域大,但也存在一级缓存中有的数据,二级缓存中没有,如使用不同的SqlSession查询数据的时候,会把查询的数据放到一级缓存中(二级缓存中没有)。

分页

插件:

  <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.1.4</version>
    </dependency>
</dependencies>

mybatis-config.xml

<plugins>
    <!--设置分页插件-->
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

设置分页参数,当前页面,每页记录数

PageHelper.startPage(1,3);

使用查询结果

PageInfo<Student>pi=new PageInfo<>(studentList);

/分页导航的第一页

System.out.println("navigateFirstPage:分页导航的第一页"+pi.getNavigateFirstPage());

//最后一页

System.out.println("navigateLastPage:分页导航的最后一页"+pi.getNavigateLastPage());

//总页数

System.out.println("navigatePages:分页导航的总页数"+pi.getPages());

//当前页

System.out.println("pageNum:当前页"+pi.getPageNum());

//当前的上一页

System.out.println("prePage:当前上一页"+pi.getPages());

//当前下页

System.out.println("nextPage"+pi.getNextPage());

//每条的数据条数

System.out.println("pageSize:每页的数据条数"+pi.getPageSize());

//当前页的开始型号

System.out.println("startRow:当前页的开始型号"+pi.getStartRow());

//结束型号

System.out.println("endRow:结束型号"+pi.getEndRow());

mapper类中的@中注解使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值