首页 > 技术文章 > Mybatis 框架教程笔记

liangls 2021-01-21 12:49 原文

 

框架

定义:

 

即:是软件开发中的一套解决方案,不同的框架解决的是不同的问题;

ORG思想

定义:Object Relational Mapping 对象关系映射

即:实体类和数据库表中的属性一一对应;让我们操作实体类就可以操作数据库表

MVC思想

Mybatis

 

学习之前的注意事项:

  1. 在 Windows 系统下,Mybatis 不区分大小写。Mac 系统下,Mybatis 区分大小写

  2.  

 

mybatis的入门

环境搭建

 

1.第一步:创建 Maven 工程并导入坐标

2.第二步:创建实体类和 dao 接口

3.第三步:创建Mybatis的主配置文件

SqlMapConfig.xml

4.第四步:创建映射配置文件

IUserDao.xml

环境搭建的注意事项:

第一个:创建 IUserDao.xml 和 IUserDao.java 时名称是为了和我们之前的知识保持一致。

在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper

所以: IUserDao 和 IUserMapper 是一样的

第二个:在IDEA中创建目录的时候,它和包是不一样的

包在创建时:com.itheima.mybatis 是三级目录

目录在创建时:com.itheima.mybatis是一级目录

第三个: Mybatis 的映射配置文件位置必须和 dao 接口的包结构相同

第四个:映射配置文件的 mapper 标签 namespace 属性的取值必须是 dao 接口的全限定类名

第五个:映射配置文件的操作配置(select),id 属性的取值必须是 dao 接口的方法名

当我们遵从了第三,四,五点之后,开发中便无需编写 dao 的实现类

mybatis 的入门案例

第一步:读取配置文件

InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");

第二步:创建 SqlSessionFactory 工厂

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);

第三步:创建 SqlSession

SqlSession session = factory.openSession();

第四步:创建 Dao 接口的代理对象

UserDao userdao = session.getMapper(UserDao.class);

第五步:执行 dao 中的方法

List<User> list = userdao.findAll();

第六步:释放资源

sesssion.close();
io.close();

注意事项:不要忘记在映射配置中告知mybatis要封装到那个实体类;

配置的方式:指定实体类的全限定类名

 

 

2020-12-05_16h51_57

 

mybatis 基于注解的入门案例:

把 IUserDao.xml 移除,在 dao 接口苦的方法上使用 @Select 注解,并且指定 SQL 语句

同时需要在 SqlMapConfig.xml 中的 Mapper 配置时,使用 class 属性指定 dao 接口苦的全限定类名

入门案例解析

image-20201205172212623

image-20201205172314352

 

 

配置文件(resources下)

log4j.properties

# Set root category priority to INFO and its only appender to CONSOLE.
# log4j.rootCategory=INFO, CONSOLE         debug info warn error fatal
log4j.rootCategory=debug,CONSOLE, LOGFILE

log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

以上文件无需修改,拷贝到 resources 下即可

mybatis 的主配置文件(SqlMapConfig.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="mysql">
       <!-- 配置mysql的环境-->
       <environment id="mysql">
           <!-- 配置事务的类型 -->
           <transactionManager type="JDBC"></transactionManager>
           <!-- 配置数据源(连接池) -->
           <dataSource type="POOLED">
               <!-- 配置数据库的4个基本信息-->
               <property name="driver" value="com.mysql.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://localhost:3306/exercise"/>
               <property name="username" value="root"/>
               <property name="password" value="root"/>
           </dataSource>
       </environment>
   </environments>


   <!--指定配置文件的位置,映射配置文件指的是每个独立Dao独立的配置文件-->
   <mappers>
       <mapper resource="com/dream/dao/UserDao.xml"/>
   </mappers>
   
</configuration>

实体类的配置文件

<?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.dream.dao.UserDao">

    <!-- 配置查询所有-->
    <select id="findAll"  resultType="com.dream.domain.User">
        select * from user
    </select>

    <!-- 配置插入新数据-->
    <insert id="saveUser" parameterType="com.dream.domain.User">
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>

</mapper>

在 mapper 内添加需要用到的 SQL 语句

 

模糊查询

有两种方式

一、在查询语句中添加 “%”

接口内

image-20201205174937716

实体配置文件

image-20201205174927539

测试类

2020-12-05_17h45_28

注意:

若使用第一种方式,则与其他语句相似操作即可

若采用第二种方式,即在配置文件中添加 “%” ,需要注意的是:必须使用 ‘%%’,源码中此处采用了 map 的方式,键值为 value,所以此处必须为 value

 

入门案例中设计模式的分析

mybatis 使用了哪些模式

image-20201205175818049

优点:

构建者模式:把对象的创建细节隐藏,使用者直接调用方法即可拿到对象

工厂模式:解耦(降低类之间的依赖关系)

代理模式:不修改源码的基础上,对已有方法增强

读取XML配置文件

XML文件的解析有多种方法

1、DOM解析(java官方提供)

2、SAX解析(java官方提供)

3、JDOM解析(第三方提供)

4、DOM4J提供(第三方提供)

mybatis 使用的是 DOM4J 方式来解析 XML 配置文件

文件的读取路径

读取文件的路径方法有:

1、相对路径

2、绝对路径

3、类加载器

4、Select

  • 在本地使用相对路径和绝对路径

  • 在项目中使用类加载器和 Select

在 mybatis 中,XML 文件的读取使用 SelectContext 对象的 getReadPath();

 

自定义 Mybatis 的分析:

Mybatis 在使用代理 dao 的方式实现增删改查时做什么事呢?

只有两件事:

第一:创建代理对象

第二:在代理对象中调用 selectList

 

Mybatis 的 CRUD

 

 

 

Mybatis 中的参数深入及结果集的深入

 

 

Mybatis 中基于传统 dao 的方式(编写 dao 的实现类)

 

 

 

 

Mybatis 中的配置(主配置文件:SqlMapConfig.xml)

 

 

 

 

OGNL 表达式

Object Graphic Navigation Language

对象 图 导航 语言

使用

它是通过对象的取值方法来获取数据,在写法上把 get 省略了

 

eg:

我们获取用户的名称

类中的写法: user.getUsername();

OGNL表达式的写法:user.username;

mybatis 中为什么能直接写 username,而不用 user. 呢?

因为在 parameterType 中已经提供了属性所属的类,所以此时不需要写对象名

 

SqlMapConfig.xml 配置文件

配置内容

配置 properties

可以在标签内部配置连接数据库的信息,也可以通过属性应用外部配置文件信息

一、

resource 属性: 常用

用于指定配置文件的位置,是按照类路径的写法来写,并且必须存于类路径下

2020-12-08_16h41_54

2020-12-08_16h42_10

 

二、

url 属性:

是要求按照 url 的写法来写地址

URL:Uniform Resoures Locator 统一资源定位符。它是可以唯一标识一个资源的位置

它的写法:

http://localhost:8080/mybatisserver/demo1Servlet

协议 主机 端口 URI

URI:Uniform Resource Identifier 统一资源标识符。他是在应用中可以唯一定位一个资源的。

2020-12-08_16h47_32

 

配置 typeAliases

typeAliases 配置别名,他只能配置 domain 中类的别名

一、

typeAlias 用于配置别名,type属性指定的是实体类全限定类名;alias 属性指定别名,当指定别名就不在区分大小写

2020-12-08_17h08_47

2020-12-08_17h10_46

 

二、

package 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写

2020-12-08_17h15_00

2020-12-08_17h10_46

 

配置 Mappers

package 标签用于指定 dao 接口所在的包,当指定之后就不需要在写 mapper以及 resource 或者 class 这里没有运行出来

2020-12-08_17h36_24

 

 

 

 

 

 

 

连接池

优点

在实际开发中都会使用连接池

因为他可以减少我们获取连接所消耗的时间

Mybatis 中的连接池

Mybatis 中连接池的配置

配置的位置:

主配置文件 SqlMapConfig.xml 中 dataSource 标签,type 属性就是表示采用何种连接池方式

type 属性的取值:

	##### POOLED

采用传统的 javax.sql.DataSource 规范中的连接池,mybatis中有针对规范的实现

	##### UNPOOLED

采用传统的获取连接的方式,虽然也实现了 javax.sql.DataSource 接口,但是并没有使用池的思想

	##### JNDI

采用服务为其提供的JNDI 技术实现,来获取 DataSource 对象,不同的服务器所能拿到的 DataSource 是不一样的

注意:如果不是web或者maven工程,是不能使用的

 

 

 

事务

定义:

 

 

 

事务的特性

原子性(Atomocity)

隔离性(Consistency)

一致性(Isolation)

持久性(Durability)

 

 

不考虑隔离性会产生的3个问题

读未提交 (Read Uncommited)

读已提交 (Read Committed)

可重复读 (Repeatable Read)

串行化 (Serialization)

 

 

 

解决办法:

四种隔离级别

 

它是通过 sqlsession 对象的 commit 方法和 rollback 方法实现事务的提交和回滚

 

 

 

Mybatis 中映射文件的深入

if 标签

根据实体类的不同取值,使用不同的 SQL 语句来进行查询,比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在多条件组合查询中经常碰到

2020-12-09_00h49_06

2020-12-09_00h49_22

 

注意:多条件查询时,并列条件组合必须用 and ,而不能用 &&

2020-12-09_01h00_40

2020-12-09_01h00_51

 

where 标签

根据实体类的不同取值,使用不同的 SQL 语句来进行查询,但是查询条件不确定。而查询条件又多的时候,我们可以通过 where 标签来实现多条件,且不确定条件查询

2020-12-09_00h49_06

2020-12-09_00h53_48

2020-12-09_00h52_56

 

 

foreach 标签

根据实际开发要求,应对需要查询多 ID 时,此时需要将 ID 包装到集合中,通过包装类来实现映射

2020-12-09_15h50_53

2020-12-09_15h50_30

2020-12-09_15h45_46

 

Result 标签

配置文件中:

result 标签中

property 表示 实体类中 get 和 set 方法后面的属性

colum 表示 SQL 语句查询结果中的结果列

2020-12-12_11h54_58

 

抽取重复的 SQL 语句

抽取重复的 SQL 语句为其添加别名

注意:若在 if 标签或 where 标签中引用,不能在 SQL 标签中的 SQL 语句中添加分号2020-12-09_18h12_24

 

 

mybatis 中的多表查询

表之间的关系

一对多

多对一

一对一

多对多

 

mybatis 中的多表查询

示例:用户和账户

一个用户有多个账户

一个账户只能属于一个用户(多个账户也可以属于同一个用户)

步骤

1、建立两张表

让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加

2、建立两个实体类:用户表,账户表

让用户和账户的实体类能体现出一对多的关系

3、建立两个配置文件

用户的配置文件

账户的配置文件

4、实现配置

当我们查询用户时,可以同时得到用户下包含的账户信息

当我们查询账户时,可以同时得到账户下的所属用户信息

 

一对一

第一种方式:(较古老)

添加第三张表信息,在第三张表中加入需要的字段信息。使用及应用于之前类似

2020-12-10_10h00_56

2020-12-10_09h59_59

 

第二种方式

一、在从表中添加主表的实体属性

2020-12-10_11h40_57

二、然后在从表的映射配置文件中添加映射信息

2020-12-10_11h33_11

 

 

一对多

一、在主表中添加从表的集合引用

2020-12-10_12h17_58

 

二、主表映射配置文件的参数设置

2020-12-10_12h19_31

 

三、 SQL 语句查询结果

2020-12-10_12h19_49

注意:mybatis是很智能且强大的,它会在查询结果中将重复的数据删除,只保留一条

 

多对多

示例:用户和角色

一个用户有多个角色

一个角色可以赋予多个用户

步骤

1、建立两张表

用户表

角色表

用户表和角色表具有多对多的关系,需要使用中间表,中间表包含各自的主键,在中间表中是外键

image-20201212110747902

2、建立两个实体类:

用户实体类

角色实体类

让用户和角色能体现多对多的关系,各自包含对方一个集合引用

2020-12-12_10h55_11

2020-12-12_11h09_37

3、建立两个配置文件

用户的配置文件

2020-12-12_11h30_47

角色的配置文件

2020-12-12_10h56_45

配置文件中:

result 标签中

property 表示 实体类中 get 和 set 方法后面的属性

colum 表示 SQL 语句查询结果中的结果列

开发注意:

实际开发中,在SQL语句很长,很复杂的情况下,必须在每行尾或者行头添加空格,以防止字符串拼接操作,导致的错误

4、实现配置

当我们查询用户时,可以同时得到用户下包含的角色信息

image-20201212112157782

2020-12-12_11h45_52

当我们查询角色时,可以同时得到角色所赋予的用户信息

image-20201212112012933

2020-12-12_11h14_37

 

 

JNDI

JNDI

Java Naming And Directory Interface

是 SUN 公司推出的一套规范,属于 JavaEE 技术之一 。目的是模仿 Windows 系统中的注册表。

 

。。。。。。。。。。。

 

 

 

 

Mybatis 的延迟加载

问题:

在一对多中,当我们有一个用户,他有100个账户。

在查询用户的时候,要不要把关联的账户查出来?

在查询账户的时候,要不要把关联的用户查出来?

解决:

在查询用户是,用户下的账户信息,什么时候用,什么时候查询

在查询账户时,账户所属用户信息,随着账户查询时一起查询出来

 

延迟加载和立即加载

延迟加载

在真正使用数据是才发起查询,不用的时候不查询,按需加载(懒加载)

立即加载

不管用不用,只要一调用方法,马上发起查询

 

在对应四中表关系中:一对一;一对多;多对一;多对多

一对;多对:通常情况下都是采用延迟加载

多对;一对:通常情况下都是采用立即加载

 

Mybatis 中的缓存

什么是缓存

存在于内存中的临时数据

 

为什么使用缓存

减少和数据库的交互次数,提高执行效率

 

什么样的数据能使用缓存,什么样的数据不适合用缓存

适用于缓存:

经常查询并且不经常改变的

数据的正确与否对最后结果影响不大的

不适用于缓存

经常改变的数据

数据的正确与否对最终结果影响很大的

例如:商品的库存,银行的汇率,股市的牌价

 

Mybatis 中的一级缓存和二级缓存

一级缓存(默认无需设置)

它指的是Mybatis中SqlSession对象的缓存

当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中。

该区域的结构是一个Map。当我们在此查询到同样的数据,mybatis会先去sqlSession中查询是否有,有的话直接拿出来用。

 

当SqlSession对象消失时,Mybatis的一级缓存也就消失了

SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit() , close() 等方法时,就会清空一级缓存

image-20201220204603702

 

二级缓存(需设置)

它指的是 Mybatis 中 SqlSessionFactory 对象的缓存。由同一个 SqlSessionFactory 对象创建的 SqlSession 共享其缓存

二级缓存的使用步骤:

第一步:让 Mybatis 框架支持二级缓存(在 SqlMapConfig.xml) 中配置

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

第二步:让当前的映射文件支持二级缓存(在 IUserDao.xml) 中配置

<cache/>

第三步:让当前的操作支持二级缓存(在 Select 标签中配置)

<select id="findById" parameterType="int" resultTyp="user" useCache="true">
	select * ferm user where id=#{uid}
</select>

主配置文件

image-20201220211108395

实体类配置文件

image-20201220211305373

测试类

image-20201220211010374

注意:

再次强调:二级缓存内存放的是数据,而不是对象。当每次从二级缓存中拿取数据时,会重新进行封装对象操作,所以从二级缓存内取到的对象不是同一个

 

Mybatis 中的注解开发

在 Mybatis 框架中,只能存在一种解析方式,即要么使用配置文件方式,要么使用注解方式,不能两者同时存在

 

前期准备

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima.mybatis</groupId>
    <artifactId>day05_mybatis_annotation02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

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

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.4.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

Mybatis 所需要的配置文件

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/exercise?useSSL=false
jdbc.username=root
jdbc.password=root

log4j.properties

log4j.rootCategory = debug,CONSOLE,LOGFILE

log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

log.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x -%m\n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x -%m\n

SqlMapConfig.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>

    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!-- 配置别名 -->
    <typeAliases>
        <package name="com.lgl.mybatis.domain.User"/>
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <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>
        </environment>
    </environments>

    <!-- 指定带有注解的 dao 接口所在位置-->
    <mappers>
        <package name="com.lgl.mybatis.dao"/>
    </mappers>

</configuration>

 

CRUD 操作

实体类

package com.lgl.mybatis.Test;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    private int id;
    private String username;
    private String address;
    private Date birthday;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", address='" + address + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

实体类 dao 接口

package com.lgl.mybatis.dao;

import com.lgl.mybatis.Test.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;

public interface IUserDao {
    /**
     * 查询所有用户方法
     * @return
     */
    @Select("select * from user")
    List<User> findAll();

    /**
     * 通过主键 id 查询该用户所有信息
     * @param id
     * @return
     */
    @Select("select * from user where id=#{id}")
    User findOne(int id);

    /**
     * 添加新用户信息
     * @param user
     */
    @Insert("insert into user(username,address,birthday) values (#{username},#{address},#{birthday})")
    Boolean saveUser(User user);

    @Delete("delete  from user where id=#{id}")
    /** 通过主键删除用户信息 */
    Boolean deleteUser(int id);

    @Update("update user set username=#{username},address=#{address},birthday=#{birthday} where id=#{id}")
    Boolean updateUser(User user);

    /**
     * 查询用户数据条数
     * @return
     */
    @Select("select count(*) from user ")
    int findTotal();

    /**
     * 查询用户名相似的用户集合
     * @param name
     * @return
     */
//    @Select("select * from user where username like #{name}")
    @Select("select * from user where username like '%${value}%' ")
    List<User> findByName(String name);
}

 

测试类

package com.lgl.mybatis.Test;

import com.lgl.mybatis.dao.IUserDao;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class MybatisAnoTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao dao;
    @Before
    public void before() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        dao = session.getMapper(IUserDao.class);
    }

    @After
    public void after() throws Exception{
        session.commit();
        session.close();
        in.close();
    }

    @Test
    public void TestFind(){
        List<User> all = dao.findAll();
        for(User a : all){
            System.out.println(a);
        }

    }

    @Test
    public void TestFindOne(){
        User one = dao.findOne(1);
        System.out.println(one);
    }

    @Test
    public void TestUpdate(){
        User u = new User();
        u = dao.findOne(56);
        System.out.println(u);
        u.setUsername("cnm");
        u.setBirthday(new Date());
        u.setAddress("YN");
        System.out.println(u);
        System.out.println(dao.updateUser(u));
    }

    @Test
    public void TestSave(){
        User u = new User();
        u.setAddress("aa");
        u.setBirthday(new Date());
        u.setUsername("bb");
        System.out.println(dao.saveUser(u));
    }

    @Test
    public void TestDelete(){
        System.out.println(dao.deleteUser(65));
    }

    @Test
    public void TestTotal(){
        System.out.println(dao.findTotal());
    }

    @Test
    public void TestFindByName(){
//        List<User> byName = dao.findByName("%王%");
        List<User> byName = dao.findByName("王");
        for(User u:byName){
            System.out.println(u);
        }
    }
}

 

别名的 CRUD 操作

说明

  • 配置文件与上同

  • 此开发方法存在于数据库的列名与实体类的属性名不相同时

 

实体类

package com.lgl.mybatis.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    private int userId;
    private String userName;
    private String userAddress;
    private Date userBirthday;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userAddress='" + userAddress + '\'' +
                ", userBirthday=" + userBirthday +
                '}';
    }
}

实体类 dao 接口

image-20201220222956434

image-20201220223615281

package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface IUserDao {
    /**
     * 查询所有用户方法
     * @return
     */
    @Select("select * from user")
    @Results(id="userMap" ,value = {
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "birthday",property = "userBirthday")
    })
    List<User> findAll();

    /**
     * 通过主键 id 查询该用户所有信息
     * @param id
     * @return
     */
    @Select("select * from user where id=#{id}")
    @ResultMap(value={"userMap"})
    User findOne(int id);

    /**
     * 添加新用户信息
     * @param user
     */

    @Insert("insert into user(username,address,birthday) values (#{userName},#{userAddress},#{userBirthday})")
    @ResultMap(value={"userMap"})
    Boolean saveUser(User user);

    @ResultMap(value={"userMap"})
    @Delete("delete  from user where id=#{id}")
    /** 通过主键删除用户信息 */
    Boolean deleteUser(int id);

    @ResultMap(value={"userMap"})
    @Update("update user set username=#{userName},address=#{userAddress},birthday=#{userBirthday} where id=#{userId}")
    Boolean updateUser(User user);

    /**
     * 查询用户数据条数
     * @return
     */
    @Select("select count(*) from user ")
    int findTotal();

    /**
     * 查询用户名相似的用户集合
     * @param name
     * @return
     */
    @ResultMap("userMap")
//    @Select("select * from user where username like #{name}")
    @Select("select * from user where username like '%${value}%' ")
    List<User> findByName(String name);
}

 

测试类

package com.lgl.mybatis.domain;

import com.lgl.mybatis.dao.IUserDao;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class MybatisAnoTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao dao;
    @Before
    public void before() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        dao = session.getMapper(IUserDao.class);
    }

    @After
    public void after() throws Exception{
        session.commit();
        session.close();
        in.close();
    }

    @Test
    public void TestFind(){
        List<User> all = dao.findAll();
        for(User a : all){
            System.out.println(a);
        }

    }

    @Test
    public void TestFindOne(){
        User one = dao.findOne(1);
        System.out.println(one);
    }

    @Test
    public void TestSaveUser(){
        User u = new User();
        u.setUserName("aa");
        u.setUserAddress("云南");
        u.setUserBirthday(new Date());
        System.out.println(dao.saveUser(u));
    }

    @Test
    public void TestDelete(){
        Boolean aBoolean = dao.deleteUser(67);
        System.out.println(aBoolean);
    }

    @Test
    public void TestUpdate(){
        User u = new User();
        u.setUserId(66);
        u.setUserName("bb");
        u.setUserBirthday(new Date());
        u.setUserAddress("贵州");
        System.out.println(dao.updateUser(u));
    }

    @Test
    public void TestFindTotal(){
        System.out.println(dao.findTotal());
    }

    @Test
    public void TestFindName(){
        System.out.println(dao.findByName("王"));
    }
    
}

 

注解开发一对一(一对多)

前期准备

  • 添加实体类 Account

 

实体类:

image-20201220231405015

package com.lgl.mybatis.domain;

import java.io.Serializable;

public class Account implements Serializable {

    private int id;
    private int aid;
    private double money;

//    多对一(mybatis中称之为一对一的映射);一个账户只能属于一个用户
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAid() {
        return aid;
    }

    public void setAid(int aid) {
        this.aid = aid;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "account{" +
                "id=" + id +
                ", aid=" + aid +
                ", money=" + money +
                '}';
    }
}
package com.lgl.mybatis.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    private int userId;
    private String userName;
    private String userAddress;
    private Date userBirthday;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userAddress='" + userAddress + '\'' +
                ", userBirthday=" + userBirthday +
                '}';
    }
}

实体类 dao 接口

image-20201220232245994

 

IAccountDao.java

package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.Account;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface IAccountDao {

    /**
     * 查询所有账户,并且获取每个账户下用户的所属信息
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "aid",property = "aid"),
            @Result(column = "money",property = "money"),
            @Result(property = "user",column = "aid",
                    one = @One(select = "com.lgl.mybatis.dao.IUserDao.findOne",
                            fetchType = FetchType.EAGER))
    })
    List<Account> findAll();
}

IUserDao.java

package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface IUserDao {
    /**
     * 查询所有用户方法
     * @return
     */
    @Select("select * from user")
    @Results(id="userMap" ,value = {
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "birthday",property = "userBirthday")
    })
    List<User> findAll();

    /**
     * 通过主键 id 查询该用户所有信息
     * @param id
     * @return
     */
    @Select("select * from user where id=#{id}")
    @ResultMap(value={"userMap"})
    User findOne(int id);

    /**
     * 添加新用户信息
     * @param user
     */

    @Insert("insert into user(username,address,birthday) values (#{userName},#{userAddress},#{userBirthday})")
    @ResultMap(value={"userMap"})
    Boolean saveUser(User user);

    @ResultMap(value={"userMap"})
    @Delete("delete  from user where id=#{id}")
    /** 通过主键删除用户信息 */
    Boolean deleteUser(int id);

    @ResultMap(value={"userMap"})
    @Update("update user set username=#{userName},address=#{userAddress},birthday=#{userBirthday} where id=#{userId}")
    Boolean updateUser(User user);

    /**
     * 查询用户数据条数
     * @return
     */
    @Select("select count(*) from user ")
    int findTotal();

    /**
     * 查询用户名相似的用户集合
     * @param name
     * @return
     */
    @ResultMap("userMap")
//    @Select("select * from user where username like #{name}")
    @Select("select * from user where username like '%${value}%' ")
    List<User> findByName(String name);
}

测试类

AccountTest.java

package com.lgl.mybatis.domain;

import com.lgl.mybatis.dao.IAccountDao;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;

public class AccountTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IAccountDao dao;
    @Before
    public void before() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        dao = session.getMapper(IAccountDao.class);
    }

    @After
    public void after() throws Exception{
        session.commit();
        session.close();
        in.close();
    }

    @Test
    public void TestFind(){
        List<Account> all = dao.findAll();
        for (Account a:all){
            System.out.println("-------------每个账户信息---------------");
            System.out.println(a);
            System.out.println(a.getUser());
        }
    }
}

 

注解开发一对多(多对多)

实体类

User.java

package com.lgl.mybatis.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {

    private int userId;
    private String userName;
    private String userAddress;
    private Date userBirthday;

    //    一对多:一个用户有多个账户信息
    private List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userAddress='" + userAddress + '\'' +
                ", userBirthday=" + userBirthday +
                '}';
    }
}

 

实体类 dao 接口

IAccountDao.java

package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.Account;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface IAccountDao {

    /**
     * 查询所有账户,并且获取每个账户下用户的所属信息
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "aid",property = "aid"),
            @Result(column = "money",property = "money")
    })
    List<Account> findAll();

    /**
     * 根据用户主键查询账户信息
     * @param id
     * @return
     */
    @Select("select * from account where aid=#{aid}")
    Account findByAid(int id);
}

IUserDao.java

package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;

public interface IUserDao {
    /**
     * 查询所有用户方法
     * @return
     */
    @Select("select * from user")
    @Results(id="userMap" ,value = {
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "birthday",property = "userBirthday"),
            @Result(property = "accounts",column = "id",
                    many = @Many(select = "com.lgl.mybatis.dao.IAccountDao.findByAid",
                            fetchType=FetchType.LAZY))
    })
    List<User> findAll();

    /**
     * 通过主键 id 查询该用户所有信息
     * @param id
     * @return
     */
    @Select("select * from user where id=#{id}")
    @ResultMap(value={"userMap"})
    User findOne(int id);

    /**
     * 添加新用户信息
     * @param user
     */

    @Insert("insert into user(username,address,birthday) values (#{userName},#{userAddress},#{userBirthday})")
    @ResultMap(value={"userMap"})
    Boolean saveUser(User user);

    @ResultMap(value={"userMap"})
    @Delete("delete  from user where id=#{id}")
    /** 通过主键删除用户信息 */
    Boolean deleteUser(int id);

    @ResultMap(value={"userMap"})
    @Update("update user set username=#{userName},address=#{userAddress},birthday=#{userBirthday} where id=#{userId}")
    Boolean updateUser(User user);

    /**
     * 查询用户数据条数
     * @return
     */
    @Select("select count(*) from user ")
    int findTotal();

    /**
     * 查询用户名相似的用户集合
     * @param name
     * @return
     */
    @ResultMap("userMap")
//    @Select("select * from user where username like #{name}")
    @Select("select * from user where username like '%${value}%' ")
    List<User> findByName(String name);
}

测试类

package com.lgl.mybatis.domain;

import com.lgl.mybatis.dao.IUserDao;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao dao;
    @Before
    public void before() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        dao = session.getMapper(IUserDao.class);
    }

    @After
    public void after() throws Exception{
        session.commit();
        session.close();
        in.close();
    }

    @Test
    public void TestFind(){
        List<User> all = dao.findAll();
        for(User a : all){
            System.out.println("----------每个用户的信息---------------");
            System.out.println(a);
            System.out.println(a.getAccounts());
        }
    }

}

效果图

image-20201220235826523

 

注解开发二级缓存

image-20201221001452128

在需要开启二级缓存的实体类 dao 上添加注解

@CacheNamespace(blocking=true)
package com.lgl.mybatis.dao;

import com.lgl.mybatis.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;

/*
  开启二级缓存
*/

@CacheNamespace(blocking = true)
public interface IUserDao {
   /**
    * 查询所有用户方法
    * @return
    */
   @Select("select * from user")
   @Results(id="userMap" ,value = {
           @Result(id = true,column = "id",property = "userId"),
           @Result(column = "username",property = "userName"),
           @Result(column = "address",property = "userAddress"),
           @Result(column = "birthday",property = "userBirthday"),
           @Result(property = "accounts",column = "id",
                   many = @Many(select = "com.lgl.mybatis.dao.IAccountDao.findByAid",
                           fetchType=FetchType.LAZY))
  })
   List<User> findAll();

   /**
    * 通过主键 id 查询该用户所有信息
    * @param id
    * @return
    */
   @Select("select * from user where id=#{id}")
   @ResultMap(value={"userMap"})
   User findOne(int id);

   /**
    * 添加新用户信息
    * @param user
    */

   @Insert("insert into user(username,address,birthday) values (#{userName},#{userAddress},#{userBirthday})")
   @ResultMap(value={"userMap"})
   Boolean saveUser(User user);

   @ResultMap(value={"userMap"})
   @Delete("delete from user where id=#{id}")
   /** 通过主键删除用户信息 */
   Boolean deleteUser(int id);

   @ResultMap(value={"userMap"})
   @Update("update user set username=#{userName},address=#{userAddress},birthday=#{userBirthday} where id=#{userId}")
   Boolean updateUser(User user);

   /**
    * 查询用户数据条数
    * @return
    */
   @Select("select count(*) from user ")
   int findTotal();

   /**
    * 查询用户名相似的用户集合
    * @param name
    * @return
    */
   @ResultMap("userMap")
//   @Select("select * from user where username like #{name}")
   @Select("select * from user where username like '%${value}%' ")
   List<User> findByName(String name);
}

 

 

 

推荐阅读