Mybatis

                                       根据狂神老师视频写的笔记

一.简介

1.什么是Mybatis?

  • Mybatis是一款优秀的持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github

2.如何获取Mybatis?  

  • maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>

 3.持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(jdbc),io文件持久化
  • 生活:冷藏,罐头

为什么需要持久化?

  • 有一些对象不能让他丢掉 
  • 内存很贵

 4.持久层

  •  Dao层,Service层,Controller层
  • 完成持久化工作的代码块
  • 层界限明显

5.为什么需要Mybatis?

  • 帮助程序员将数据存入数据库中

  • 方便

  • 传统的JDBC代码太复杂了 ,简化成框架实现自动化

Mybatis优点? 

  • 简单易学,没有任何第三方依赖,只要两个jar文件+配置几个sql映射文件
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求
  • sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射。

  • 提供对象关系映射标签,支持对象关系组建维护。

  • 提供xml标签,支持编写动态sql。

二.Mybatis程序

 思路:搭建环境-->导入Mybatis-->编写代码-->测试

1.搭建环境 

CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'九七','123456'),
(2,'张三','123456'),
(3,'李四','123456');

新建项目

  • 新建一个普通的maven项目 
  • 删除src目录
  • 导入maven依赖
<?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>org.example</groupId>
    <artifactId>MybatisStudy</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>Mybatis-01</module>
    </modules>

    <!--导入依赖-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>


    <!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

2.创建模块

核心配置文件

<?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核心配置文件-->
<configuration>

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

    <!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/jiuqi/dao/UserMapper.xml"/>
    </mappers>

</configuration>

编写mybatis工具类

package com.jiuqi.utils;

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 java.io.IOException;
import java.io.InputStream;

//SqlSessionFactory-->sqlSession
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static{
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            //使用Mybatis第一步:获取SqlSessionFactory对象
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

3.编写代码

实体类

package com.jiuqi.pojo;

//实体类
public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

Dao接口

import com.jiuqi.pojo.User;

import java.util.List;

public interface UserDao {
    List<User> getUserList();
}

接口实现类(和web不同的是由原来的UserDaoImpl转变为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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.jiuqi.dao.UserDao">

    <!--select查询语句-->
    <select id="getUserList" resultType="com.jiuqi.pojo.User">
        select * from mybatis.user
    </select>
</mapper>

4.测试

  • 注意点:org.apache.ibatis.binding.BindingException: Type interface com.jiuqi.dao.UserDao is not known to the MapperRegistry.  在mybatis-config.xml上忘记注册Mapper,加上就好
  • maven由于他的约定大于配置,我们之后可以能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
    <!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

UserDaoTest测试

package com.jiuqi.dao;

import com.jiuqi.pojo.User;
import com.jiuqi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {
    @Test
    public void test() {
        //第一步:获得SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        try {
            //方法一:执行Sql
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            List<User> userList = userDao.getUserList();


        /*
        方式二(了解不需要掌握)
        List<User> userList = sqlSession.selectList("com.jiuqi.dao.UserDao.getUserList");
         */

            for (User user : userList) {
                System.out.println(user);
            }
        }catch (Exception e){
          e.printStackTrace();
        }finally {

            //关闭SqlSession
            sqlSession.close();
        }

    }
}

三.CRUD

注意:增删改要提交事务

1.namespace

 namespace中的包名要和接口的包名一致

2.select

选择,查询

  • id:就是对应的namespace中的上方法名
  • resultType:Sql语句的返回值 
  • parameterType:参数类型

编写接口

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

编写对应的SQL语句

<!--根据ID查询用户-->
    <select id="getUserById" resultType="com.jiuqi.pojo.User" parameterType="int">
        select * from mybatis.user where id=#{id}
    </select>

 测试

@Test
    public void getUserById() {
        //第一步:获得SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        try {
            //方法一:执行Sql
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User userById = userMapper.getUserById(1);
            System.out.println(userById);

        }catch (Exception e){
            e.printStackTrace();
        }finally {

            //关闭SqlSession
            sqlSession.close();
        }
    }

3.Insert

编写接口

int addUser(User user);

编写对应的SQL语句

<insert id="addUser"  parameterType="com.jiuqi.pojo.User">
        insert into mybatis.user (id, name, pwd) value (#{id},#{name},#{pwd});
    </insert>

测试

 @Test
    public void addUser() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

            UserMapper Mapper = sqlSession.getMapper(UserMapper.class);
            int name = Mapper.addUser(new User(4, "赵六", "123456"));
            if(name > 0){
                System.out.println("插入成功");
            }
           //提交事务
            sqlSession.commit();

            sqlSession.close();
        }

4.修改用户

编写接口

int updateUser(User user);

编写对应的SQL语句

<update id="updateUser" parameterType="com.jiuqi.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>

测试

@Test
    public void updateUser() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int name = mapper.updateUser(new User(4, "刘能", "111111"));
        sqlSession.commit();
        sqlSession.close();
    }

5.删除用户

编写接口

int deleteUser(int id);

编写对应的SQL语句

 <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>

测试

 @Test
    public void deleteUser() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(4);
        sqlSession.commit();
        sqlSession.close();
    }

6.万能Map

  •  在实体类或者数据库中的表、字段、参数过多,我们可以考虑使用Map(不正规)或者注解
  • Map传递参数,直接在sql中取出key即可
  • 对象传递参数,直接在sql中取出对象的属性即可!
  • 只有一个基本类型参数的情况下,可以直接在sql中取到

 编写接口

int addUser2(Map<String,Object> map);

编写对应的SQL语句

<insert id="addUser2"  parameterType="map">
        insert into mybatis.user (id, name, pwd) value (#{userid},#{username},#{userpwd});
    </insert>

测试

@Test
    public void addUser2() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper Mapper = sqlSession.getMapper(UserMapper.class);

        Map<String, Object> map = new HashMap<String,Object>();
        map.put("userid",5);
        map.put("username","春风");
        map.put("userpwd","223113");
        int name = Mapper.addUser2(map);
        if(name > 0){
            System.out.println("插入成功");
        }
        //提交事务
        sqlSession.commit();

        sqlSession.close();
    }

7.模糊查询怎么写? 

  • Java代码执行的时候,传递通配符% %
 List<User> userLike = Mapper.getUserLike("赵%");
  • 在sql拼接使用中使用通配符 
 select * from mybatis.user where name like "%"#{value}"%"
  •   第二种方式可能会出现bug 

 编写接口

List<User> getUserLike(String name);

编写对应的SQL语句

  <select id="getUserLike" resultType="com.jiuqi.pojo.User" parameterType="String">
        select * from mybatis.user where name like #{value}
    </select>

测试

   @Test
    public void getUserLike() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper Mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userLike = Mapper.getUserLike("赵%");


            for (User user : userLike) {
                System.out.println(user);
            }

            sqlSession.close();
    }

四.配置解析

 1.核心配置文件

  •  mybatis-config.xml
  • Mybatis的配置文件包含会深深影响Mybatis行为的设置和属性信息
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

2.环境配置(environments)

MyBatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

学会使用多套运行环境 

每个数据库对应一个 SqlSessionFactory 实例

Mybatis默认的事务管理器是JDBC(MANAGED),连接池:POOLED

3. 属性(properties)

我们可以通过properties属性来实现引用配置文件

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置[db.properties] 

编写配置文件

db.peoperties

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

在核心配置文件中引入

 <!--引入外部配置文件-->
    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="ped" value="201408181"/>
    </properties> 
  • 可以直接引入外部文件
  • 可与在其中增加一些属性配置
  • 如果两文件有同一个字段优先使用外部配置文件

xml的所有标签都有其顺序,如果不按照顺序会报错(properties,settings,typeAliases,typeHandlers,objectWrapperFactory,reflectorFactory,plugins, environments,databaseldProvider,mappers) 

4.类型别名 

  •  类型别名是为Java类型设置一个短的名字
  • 存在意义仅在于进来减少类完全限定名的冗余
 <!--可以给实体类起别名-->
    <typeAliases>
        <typeAlias type="com.jiuqi.pojo.User" alias="User"/>
    </typeAliases>

 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean


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

 在实体类少的时候使用第一种方式,实体类多的情况下使用第二种,但第一种可以自定义别名,第二种则不行,但可以通过实体类增加注解更改

@Alias("hello")
//实体类
public class User {

5.设置

这是Mybatis中极为重要的调整设置,它会改变Mybatis的运行时行为

cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置

6.其他配置

          mybatis-generator-core

          mybatis-plus

          通用mapper 

是代码更加简洁但一般不用

7.映射器(mappers)

推荐使用方式一

 MapperRegistry:注册绑定我们的Mapper文件

方式一:

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

方式二:使用class文件绑定注册

<mappers>
        <mapper class="com.jiuqi.dao.UserMapper"/>
    </mappers>

注意点:

  • 接口和配置文件必须同名
  • 接口和配置文件必须在同一个包下
  • 但第一种方式没有这些要求

方式三:使用包扫描进行注入绑定 

<mappers>
        <package name="com.jiuqi.dao"/>
    </mappers>

注意点:

  • 接口和配置文件必须同名
  • 接口和配置文件必须在同一个包下
  • 但第一种方式没有这些要求

8.生命周期和作用域

不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder:

  • 一旦创建了 SqlSessionFactory,就不再需要SqlSessionFactoryBuilder
  • 局部变量

SqlSessionFactory :

  • 可以理解为数据库连接池
  • 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 因此 SqlSessionFactory 的最佳作用域是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式

SqlSession :

  • 连接到连接池的一个请求 
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
  • 用完之后需赶紧关闭,否则资源占用

五.解决属性名和字段名不一致的问题

 1.当数据库的名字和User的名字不一致时,类型处理器会无法转换导致数据为空

public class User {
    private int id;
    private String name;
    private String password;

(1).解决方法:起别名

<select id="getUserById" resultType="com.jiuqi.pojo.User" parameterType="int">
        select id,name,pwd as password from mybatis.user where id=#{id}
    </select>

(2).resultMap

结果集映射 

<!--结果集映射-->
    <resultMap id="UserMap" type="User">
        <!--column数据库中的字段,property实体类的属性-->
        <result column="pwd" property="password"/>
    </resultMap>

    <!--根据ID查询用户-->
    <select id="getUserById" resultMap="UserMap">
        select *  from mybatis.user where id=#{id}
    </select>
  • resultMap 元素是 MyBatis 中最重要最强大的元素
  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了
  •  ResultMap 的优秀之处——你完全可以不用显式地配置它们

六.日志 

1.日志工厂 

如果一个数据库操作出现了异常,我们需要排错,日志就是最好的助手

以前可以用sout,debug进行排错,现在我们可以使用日志工厂 

logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
  • SLF4J
  • LOG4J(deprecated since 3.5.9) 掌握
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING      掌握
  • NO_LOGGING 

在Mybatis具体使用那个日志实现,需要在设置中设定

STDOUT_LOGGING标准日志输出

在mybits核心配置文件中,配置我们的日志

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
Opening JDBC Connection
Created connection 614685048.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@24a35978]
==>  Preparing: select * from mybatis.user where id=? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 九七, 123456
<==      Total: 1
User{id=1, name='九七', password='123456'}

2.Log4j

什么是Log4j?

  • Log4j时Apache的一个开源项目,通过使用Log4j,我么可以控制日志信息输送的目的地是控制台、文件、GUI组件 
  • 我们可以控制每一条日志的输出格式
  • 通过定义每一条日志信息的级别
  • 通过配置文件进行配置,不需要修改代码

先导入log4j的包 

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2.log4j.properties 

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/jiuqi.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

 配置log4j为日志实现

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

Log4j使用

[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VFS
[org.apache.ibatis.io.JBoss6VFS]-JBoss 6 VFS API is not available in this environment.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VirtualFile
[org.apache.ibatis.io.VFS]-VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
[org.apache.ibatis.io.VFS]-Using VFS adapter org.apache.ibatis.io.DefaultVFS
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/D:/java/MybatisStudy/Mybatis-04/target/test-classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/D:/java/MybatisStudy/Mybatis-04/target/test-classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Reader entry: UserDaoTest.class
[org.apache.ibatis.io.DefaultVFS]-Listing file:/D:/java/MybatisStudy/Mybatis-04/target/test-classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/D:/java/MybatisStudy/Mybatis-04/target/test-classes/com/jiuqi/dao/UserDaoTest.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/D:/java/MybatisStudy/Mybatis-04/target/test-classes/com/jiuqi/dao/UserDaoTest.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ����   4 9
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Reader entry: UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Listing file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao/UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao/UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ����   4 	  getUserById (I)Lcom/jiuqi/pojo/User; 
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao/UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/D:/java/MybatisStudy/Mybatis-04/target/classes/com/jiuqi/dao/UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Reader entry: <?xml version="1.0" encoding="UTF-8" ?>
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class com.jiuqi.dao.UserDaoTest matches criteria [is assignable to Object]
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class com.jiuqi.dao.UserMapper matches criteria [is assignable to Object]
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1772160903.
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[com.jiuqi.dao.UserMapper.getUserById]-==>  Preparing: select * from mybatis.user where id=? 
[com.jiuqi.dao.UserMapper.getUserById]-==> Parameters: 1(Integer)
[com.jiuqi.dao.UserMapper.getUserById]-<==      Total: 1
User{id=1, name='九七', password='123456'}
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1772160903 to pool.

 简单使用

1.在要使用Log4j的类中,导入 import org.apache.log4j.Logger;  倒错会报错

2.日志对象,参数为当前类的class

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

 3.日志级别

        logger.info("info进入testLog4j");
        logger.debug("debug:进入testLog4j");
        logger.error("error:进入testLog4j");

 七.分页

1.分页的作用?

  • 减少数据的处理量

2.使用Limit分页

语法格式:SELECT * from user limit startIndex,pageSize
SELECT * from user limit 3;    #[0,n]

3.使用Mybatis进行分页,核心SQl  

  • 接口
List<User> getUserByLimit(Map<String,Integer> map);
  • Mapper.XML
    <select id="getUserByLimit" parameterType="map" resultMap="UserMap">
        select * from mybatis.user limit #{startIndex},#{pageSize}
    </select>
  • 测试
    @Test
    public void getUserByLimit() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",0);
        map.put("pageSize",2);
        List<User> userByLimit = mapper.getUserByLimit(map);
        for (User user : userByLimit) {
            System.out.println(user);
        }
        sqlSession.close();
    }

4.RowBounds分页(了解)

不再使用SQL进行分页 

  • 接口
List<User> getUserByRowRounds();
  • mapper.xml
    <select id="getUserByRowRounds"  resultMap="UserMap">
        select * from mybatis.user
    </select>
  • 测试
 @Test
    public void getUserByRowRounds() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //RowBounds实现
        RowBounds rowBounds = new RowBounds(1, 2);

        //通过Java代码的方式实现分页
        List<User> userList = sqlSession.selectList("com.jiuqi.dao.UserMapper.getUserByRowRounds",null,rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

5.分页插件(了解)

 

以后工作可能会用 

八.注解开发 

1.面向接口编程 

真正的开发中我们一般选择面向接口编程

为什么面向接口编程?

  •  解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准使得开发更容易,规范性更好

在面向的对象的系统中,系统的各级功能都有许许多多的不同对象协作完成,这种情况下各个对象内部是如何实现自己的对系统设计人员来讲就不那么重要了

而各个对象之间的协作关系则成为系统设计的关键,小到不同类之间通信,大到各模块之间的交互,在系统设计之初都是要着重考虑,这也是系统设计的主要内容,面向接口编程就是按照这种思想来编程。

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离
  • 接口本身反映了系统设计人员对系统的抽象理解

接口应有两类:第一类是对一个个体的抽象,他可对应为一个抽象体

                         第二类是对一个个体某一方面的抽象,即形成一个抽象面

一个个体有可能有多个抽象面,抽象体和抽象面是有区别的 

三个面向的区别

  • 面向对象指我们考虑问题时以对象为单位考虑它的属性及方法
  • 面相过程指我们考虑问题时以一个机体的流程(事务过程)为单位考虑他的实现
  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现是对系统整体的架构

2.使用后注解开发 

本质:反射机制实现

底层:动态代理

注解在接口上实现

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

需要在核心配置文件中绑定接口 

 <!--绑定接口-->
    <mappers>
        <mapper class="com.jiuqi.dao.UserMapper"/>
    </mappers>

测试

    @Test
    public void getUsers() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }
            sqlSession.close();
    }

3.CRUD

我们可以在工具类(MybatisUtils)创建的时候自动提交事务

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

编写接口时增加注解 

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

    //方法存在多个参数,所有参数前面必须加@Parameter()注解
    @Select("select * from user where id = #{id}")
    User getUserById(@Param("id") int id);

    @Insert ("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
    int addUser(User user);

    @Update("update user set name=#{name},id=#{id},pwd=#{pwd} where id=#{id}")
    int updateUser(User user);

    @Delete("delete from user where id = #{id}")
    int deleteUser(@Param("id") int id);

 测试

关于@Param()注解

  • 基本类型的参数或者String类型需要加上
  • 引用类型不用加
  • 如果只有基本类型可以忽略,但是最好加上
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名
 @Test
    public void getUsers() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }
            sqlSession.close();
    }

    @Test
    public void getUserById() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(1);
        System.out.println(user);

        sqlSession.close();
    }

    @Test
    public void addUser() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.addUser(new User(7, "白也", "123456"));

        sqlSession.close();
    }

    @Test
    public void updateUser() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.updateUser(new User(7,"白也","999999"));

        sqlSession.close();
    }

    @Test
    public void deleteUser() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //底层只要应用反射机制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUser(7);

        sqlSession.close();
    }

注意:我们一定要将接口注册绑定到我们配置文件上

    <!--绑定接口-->
    <mappers>
        <mapper class="com.jiuqi.dao.UserMapper"/>
    </mappers>

 九.Lombok

Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类

@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
@Getter :使用方法同上,区别在于生成的是getter方法。
@ToString :注解在类,添加toString方法。
@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。
@NoArgsConstructor: 注解在类,生成无参的构造方法。
@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Slf4j: 注解在类,生成log变量,严格意义来说是常量。

使用步骤:

  • 在idea中安装Lombok插件
  • 在项目上导入Lombok的jar包
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
  • 使用 :
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;

}

 十.多对一处理

1.SQL:

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO teacher(`id`, `name`) VALUES `teacher`(1, '秦老师'); 

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');​

 2.测试环境搭建: 

  • 导入Lombok
   <dependencies>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

    </dependencies>
  • 新建实体类Teacher、Student
@Data
public class Student {
    private int id;
    private String name;
    //学生需要关联一个老师
    private Teacher teacher;
}
@Data
public class Teacher {
    private  int id;
    private String name;
}
  • 建立Mapper接口
public interface StudentMapper {

    //查询所有学生的信息以及对应的老师信息
    public List<Student> getStudent();

    public List<Student> getStudent2();

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

  • 建立Mapper.xml文件(可以建在资源文件夹)
    <!--按照查询嵌套处理-->
    <resultMap id="studentTeacher" type="student">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <!--复杂的属性,我们需要单独处理
        对象:association
        集合:collection
        -->
        <association column="tid" property="teacher" javaType="teacher" select="getTeacher"/>
    </resultMap>
<select id="getStudent" resultMap="studentTeacher">
    select * from student;
</select>
    <select id="getTeacher" resultType="teacher">
        select * from teacher where id = #{id}
    </select>



     <!--按照结果嵌套处理-->
    <resultMap id="studentTeacher2" type="student">
        <result column="sid" property="id"/>
        <result column="sname" property="name"/>
        <association property="teacher" javaType="teacher" >
            <result column="tname" property="name"/>
        </association>
    </resultMap>
    <select id="getStudent2" resultMap="studentTeacher2">
        select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid = t.id;
    </select>
  • 在核心配置文件中注册我们的Mapper接口或者文件
    <mappers>
        <mapper class="com.jiuqi.dao.TeacherMapper"/>
        <mapper class="com.jiuqi.dao.StudentMapper"/>
    </mappers>
  • 测试查询
@Test
    public void TeacherMapper() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        sqlSession.close();
    }


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

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

十一.一对多

1.环境搭建

  • 导入Lombok
  • 新建实体类Teacher、Student
@Data
public class Teacher {
    private  int id;
    private String name;

    //一个老师拥有多个学生
    private List<Student> students;
}
@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
  • 建立Mapper接口
 //获取老师的信息以及老师下所有学生的信息
    Teacher getTeacher(@Param("tid") int id);

    Teacher getTeacher2(@Param("tid") int id);
public List<Student> getStudent();

建立Mapper.xml文件

    <!--按结果嵌套处理-->
    <resultMap id="teacherStudent" type="teacher">
        <result column="tid" property="id"/>
        <result column="tname" property="name"/>
        <!--集合中的泛型信息我们用ofType获取-->
        <collection property="students" ofType="Student">
            <result column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="tid" property="tid"/>
        </collection>
    </resultMap>
<select id="getTeacher" resultMap="teacherStudent">
    select s.id sid,s.name sname,t.name tname,t.id tid
    from student s,teacher t
    where s.tid = t.id and t.id = #{tid};
</select>

     <!--按查询嵌套处理-->
    <resultMap id="teacherStudent2" type="teacher">
        <collection property="students" ofType="student" column="id" javaType="ArrayList" select="getStudent"></collection>
    </resultMap>
    <select id="getTeacher2" resultMap="teacherStudent2">
        select * from mybatis.teacher where id = #{tid};
    </select>
    <select id="getStudent" resultType="student">
        select * from mybatis.student where tid = #{id};
    </select>
  • 在核心配置文件中注册我们的Mapper接口或者文件
  • 测试查询
    @Test
    public void getTeacher() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        sqlSession.close();
    }


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

小结

1.关联-association【多对一】 

2.集合-collection【一对多】

3.javaType & ofType?

  • javaType用来指定实体类中的属性类型
  • ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

注意:

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中属性名和字段名问题
  • 如果问题不好排除可以使用日志 

 面试高频:

  • Mysql引擎
  • innoDB底层原理
  • 索引
  • 索引优化

 十二.动态SQL

1.什么是动态SQL?

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

SQL 语句拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号,利用动态 SQL,可以彻底摆脱这种痛苦。

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

2.搭建环境

CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8

3.创建一个基础工程

1.导包

2.编写配置文件

<settings>
        <!--标准日志工厂-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--是否开启自动驼峰命名规则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

3.编写实体类

public class Blog {
    private int id;
    private String title;
    private String author;
    private Date create_time;
    private int views;
}
 public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

4.编写实体类对应的Mapper和Mapper.xml文件

public interface BlogMapper {
    //插入数据
    int addBolg(Blog blog);

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiuqi.dao.BlogMapper">

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

4.IF 

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

 5.choose(when,otherwise)

<select id="queryBlogChose" resultType="blog" parameterType="map">
       select * from mybatis.blog
       <where>
           <choose>
               <when test="title != null">
                   title = #{title}
               </when>
               <when test="author != null">
                   and author = #{author}
               </when>
               <otherwise>
                   and views = #{views}
               </otherwise>
           </choose>
       </where>
    </select>

6.trim(where,set)

 where后如果是and和or或者没有值会自动取消导致代码报错我们用where标签会解决这个问题

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

我们也可以通过自定义 trim 元素来定制 where 元素的功能 

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号 

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

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

 所谓的动态SQL,本质还是SQL语句,只是我们在SQL层面去执行一个逻辑代码

7.SQL片段

有些时候我们会将一些功能的地方抽取出来,方便复用

1.使用sql标签抽取公共部分

    <!--代码复用-->
    <sql id="if-title">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>

2.在需要使用的地方使用include标签引用 

 <include refid="if-title"></include>

 注意事项:

  • 最好基于单表来定义SQL片段
  • 不要存在where标签

8.Foreach 

 动态SQL的另外一个常用的操作需求是对一个集合进行遍历,通常在in条件语句

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

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性按照SQL的格式去排列组合就行了

十三. 缓存

1.简介

什么是缓存 

  • 存在内存中的临时数据
  • 将用户经常查询放在缓存(内存)中,用户去查询数据就不用从此磁盘(关系型数据库数据文件)查询,直接缓存查询提高查询效率,解决高并发系统问题 

什么样的数据可以使用缓存?

  • 经常查询并且不经常改变数据

2.Mybatis缓存 

 Mybatis包含一个非常强大的查询缓存特性他可以非常方便的定制和配置缓存极大的提高查询效率 

 Mybatis系统中默认定义两级缓存:一级缓存和二级缓存

  • 默认情况下只有一级缓存开启(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,它基于namespace级别的缓存
  • 为提高拓展性Mybatis定义缓存接口Cache我们可以通过实现Cache接口来自定义二级缓存

3.一级缓存 

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中
  • 如果需要再次获取相同的数据直接从缓存中拿 

步骤:

  • 开启日志
  • 测试在一个Session中查询两次相同的记录
  • 查看日志输出
Opening JDBC Connection
Created connection 1209669119.
==>  Preparing: select * from mybatis.user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 九七, 123456
<==      Total: 1
User(id=1, name=九七, pwd=123456)
User(id=1, name=九七, pwd=123456)
true
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@481a15ff]
Returned connection 1209669119 to pool.

缓存失效的情况:

  • 查询不同的东西
  • 增删改操作可能会改变原来的数据,所以必定会刷新缓存! 
  • 查询不同的Mapper.xml
  • 手动清除(对一级缓存无效)

 注意:一级缓存默认是开启的只在一次SqlSession中有效,也就是拿到链接倒关闭链接

一级缓存就是一个Map

4.二级缓存

二级缓存也叫全局缓存,一级缓存作用域太低所以产生二级缓存

基于nameSpace级别的缓存,一个名称空间对应一个二级缓存

工作机制:

  • 一个会话查询一条数据,这个数据就会被放当前会话的一级缓存中
  • 如果当前会话关闭了,这个会话对应的一级缓存也就没了,但是我们想要的是会话关闭了一级缓存中的数据被保存到二级缓存中 
  • 新的会话查询信息就可以从二级缓存中获取内容
  • 不同的mapper查询出的数据会放在自己对应的缓存(map)中

步骤:

  • 开启全局缓存
   <settings>
        <!--标准日志工厂-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        
        <!--显示的开启全局缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
  • 在要使用二级缓存的Mapper中开启
<!--在当前Mapper.xml中使用二级缓存-->
    <cache/>

         也可以自定义参数 

<!--在当前Mapper.xml中使用二级缓存
eviction="" 使用策略
flushInterval="" 每隔多久刷新一次
size=""  最多存多少缓存
readOnly=""  是否只读

-->
    <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>
  •  测试

        问题:我们需要将实体类序列化否则就会报错

实体类没序列化的报错信息:java.io.NotSerializableException: com.jiuqi.pojo.User

小结:

  • 只要开启二级缓存在同一个Mapper下就有效
  • 所有的数据都会先存放在一级缓存中只有当会话提交后关闭时才会提交到二级缓存 

5.缓存原理

 缓存顺序:先看二级缓存有无查询数据--->再看一级缓存有没有--->最后查询数据库

6.自定义缓存ehcache

Ehcache是一种广泛使用的开源Java分布式缓存,主要面向通用缓存

1.使用ehcache先导包

        <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.2.1</version>
        </dependency>

2.ehcache

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="./tmpdir/Tmp_EhCache"/>

    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>

 3.在mapper指定使用我们的缓存实现

    <!--自定义缓存-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

当然我们也可以自己写缓存,只继承cache也可以实现简单缓存,但要想写复杂的会非常难,没有必要深究,我们以后会用Redis数据库来做缓存 

24道练习题

1.Bill 

Bil实体类

package com.jiuqi.pojo;


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

import java.math.BigDecimal;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Bill {
    private Integer id;   //id
    private String billCode; //账单编码
    private String productName; //商品名称
    private String productDesc; //商品描述
    private String productUnit; //商品单位
    private BigDecimal productCount; //商品数量
    private BigDecimal totalPrice; //总金额
    private Integer isPayment; //是否支付
    private Integer createdBy; //创建者
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者
    private Date modifyDate;//更新时间
    private Integer providerId; //供应商ID

}

BillMapper

package com.jiuqi.dao.bill;

import com.jiuqi.pojo.Bill;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface BillMapper {

    //根据供应商Id查询订单数量
    int getBillCountByProviderId(@Param("providerId") Integer providerId);

    //增加订单
    int add(Map<String,Object> map);

    //通过查询条件获取供应商列表-getBillList
    List<Bill> getBillList(Map map);

    //通过条件查询,查询供货商数量
    int getBillCount(@Param("productName") String productName,
                     @Param("providerId") String providerId,
                     @Param("isPayment") String isPayment
                            );

    //通过delId删除Bill
    int deleteBillById(@Param("id") Integer id);

    //通过billId获取Bill
    Bill getBillById(@Param("id") Integer id);

    //修改订单信息
    int modify(Map map);

    //根据供应商Id删除订单信息
    int deleteBillByProviderId(@Param("providerId") Integer providerId);




}

BillMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiuqi.dao.bill.BillMapper">

<cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

    <select id="getBillCountByProviderId" resultType="int" parameterType="Integer">
        select count(1) from smbms.smbms_bill where providerId = #{providerId}
    </select>

    <insert id="add"  parameterType="map">
        insert into smbms.smbms_bill(id, billCode, productName, productDesc, productUnit,
                                     productCount, totalPrice, isPayment, createdBy, creationDate,
                                     modifyBy, modifyDate, providerId)
        values(#{id}, #{billCode}, #{productName},#{productDesc}, #{productUnit}, #{productCount}, #{totalPrice},
            #{isPayment}, #{createdBy}, #{creationDate}, #{modifyBy}, #{modifyDate}, #{providerId})
    </insert>

    <select id="getBillList" resultType="Bill">
        select p.* from smbms.smbms_bill b,smbms.smbms_provider p where b.providerId = p.id
          <if test="productName != null">
              and productName like #{productName}
          </if>
          <if test="providerId != null">
              and providerId = #{providerId}
          </if>
          <if test="isPayment != null">
              and isPayment = #{isPayment}
          </if>
        limit #{from},#{pageSize}

    </select>

    <select id="getBillCount" resultType="Integer">
        select count(1) from smbms.smbms_bill
        <where>
        <if test="productName != null">
             productName like "%"#{productName}"%"
        </if>
        <if test="providerId != null">
            and providerId = #{providerId}
        </if>
        <if test="isPayment != null">
            and isPayment = #{isPayment}
        </if>
        </where>
    </select>

    <delete id="deleteBillById" parameterType="Integer">
        delete from smbms.smbms_bill where id = #{id}
    </delete>
    
    <select id="getBillById" parameterType="Integer" resultType="bill">
        select * from smbms.smbms_bill where id = #{id}
    </select>

    <update id="modify" parameterType="map">
        update smbms.smbms_bill
        <set>
            <if test="id != null">
                id = #{id},
            </if>
            <if test="billCode != null">
                billCode = #{billCode},
            </if>
            <if test="productName != productName">
                productName = #{productName},
            </if>
            <if test="productDesc != null">
                productDesc = #{productDesc},
            </if>
            <if test="productUnit != null">
                productUnit = #{productUnit},
            </if>
            <if test="productCount != null">
                productCount = #{productCount},
            </if>
            <if test="totalPrice != null">
                totalPrice = #{totalPrice},
            </if>
            <if test="isPayment != null">
                isPayment = #{isPayment},
            </if>
            <if test="createdBy != null">
                createdBy = #{createdBy},
            </if>
            <if test="creationDate != null">
                creationDate = #{creationDate}
            </if>
            <if test="modifyBy != null">
                modifyBy = #{modifyBy},
            </if>
            <if test="modifyDate != null">
                modifyDate = #{modifyDate},
            </if>
            <if test="providerId != null">
                providerId = #{providerId}
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="deleteBillByProviderId" parameterType="Integer">
        delete from smbms.smbms_bill where providerId = #{providerId}
    </delete>

</mapper>

Bill测试

package com.jiuqi.dao;

import com.jiuqi.dao.bill.BillMapper;
import com.jiuqi.pojo.Bill;
import com.jiuqi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;

public class BillMapperTest {
    @Test
    public void getBillCountByProviderId() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        int billCountByProviderId = mapper.getBillCountByProviderId(7);
        System.out.println(billCountByProviderId);

        sqlSession.close();
    }
    @Test
    public void add() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        HashMap<String,Object> map = new HashMap<String,Object>();
        map.put("id","99");
        map.put("billCode","BILL2016_001");
        map.put("productName","小麦果汁");
        map.put("productDesc","饮料");
        map.put("productUnit","瓶");
        map.put("productCount","100");
        map.put("totalPrice","1000");
        map.put("isPayment","2");
        map.put("createdBy","1");
        try {
            map.put("creationDate",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-05-01 12:21:11"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        map.put("providerId","111");
        mapper.add(map);
        sqlSession.close();
    }

    @Test
    public void getBillList() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        HashMap map = new HashMap();
        map.put("productName","%麦%");
        map.put("providerId","16");
        map.put("isPayment","2");
        map.put("from",0);
        map.put("pageSize",9);
        mapper.getBillList(map);


        sqlSession.close();
    }

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

        mapper.getBillCount("小麦","16","2");

        sqlSession.close();
    }

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

        mapper.deleteBillById(99);

        sqlSession.close();
    }

    @Test
    public void getBillById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        Bill billById = mapper.getBillById(1);
        System.out.println(billById);

        sqlSession.close();
    }

    @Test
    public void modify() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        HashMap map = new HashMap();
        map.put("id","1");
        map.put("billCode","BILL2016_001");
        map.put("productName","小麦果汁");
        map.put("productDesc","饮料");
        map.put("productUnit","瓶");
        map.put("productCount","200");
        map.put("totalPrice","6000");
        map.put("isPayment","2");
        map.put("createdBy","1");
        mapper.modify(map);

        sqlSession.close();
    }


    @Test
    public void deleteBillByProviderId() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BillMapper mapper = sqlSession.getMapper(BillMapper.class);
        mapper.deleteBillByProviderId(111);

        sqlSession.close();
    }


}

2.Provider

provider实体类

package com.jiuqi.pojo;

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

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Provider {

    private Integer id;   //id
    private String proCode; //供应商编码
    private String proName; //供应商名称
    private String proDesc; //供应商描述
    private String proContact; //供应商联系人
    private String proPhone; //供应商电话
    private String proAddress; //供应商地址
    private String proFax; //供应商传真
    private Integer createdBy; //创建者
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者
    private Date modifyDate;//更新时间
    private Bill bill;

}

ProviderMapper

package com.jiuqi.dao.provider;


import com.jiuqi.pojo.Provider;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface ProviderMapper {

    //增加用户信息
    public int add(Map map);

    //通过条件查询providerList
    public List<Provider> getProviderList(Map map);

    //获取供应商列表
    public List<Provider> getProList();

    //通过条件查询供应商记录数
    public int getProviderCount(@Param("proName") String proName,
                                @Param("proCode") String proCode);

    //通过供应商Id删除供应商信息
    public int deleteProviderById(@Param("id") Integer delId);

    //根据供应商Id获取供应商信息
    public Provider getProviderById(@Param("id") Integer id);

    //修改供应商
    public int modify(Map map);
}

ProviderMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiuqi.dao.provider.ProviderMapper">

    <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

    <insert id="add" parameterType="map">
        insert into smbms.smbms_provider(id, proCode, proName, proDesc, proContact, proPhone, proAddress, proFax, createdBy, creationDate, modifyDate, modifyBy)
        values (#{id}, #{proCode}, #{proName}, #{proDesc}, #{proContact}, #{proPhone}, #{proAddress}, #{proFax}, #{createdBy}, #{creationDate}, #{modifyDate}, #{modifyBy})
    </insert>


    <!--熟练一下一对多,这里没必要用-->
    <resultMap id="provider1" type="provider">
        <result column="pproName" property="proName"/>
        <collection property="bill" ofType="bill">
            <result column="bid" property="id"/>
            <result column="bproductName" property="productName"/>
        </collection>
    </resultMap>
    <select id="getProviderList" resultMap="provider1">
        select b.id bid, b.productName bproductName, p.proName pproName from smbms.smbms_provider p, smbms.smbms_bill b
        where b.providerId = p.id
          <if test="proName != null">
              and proName like "%"#{proName}"%"
          </if>
          <if test="proCode != null">
              and proCode = #{proCode}
          </if>
        limit #{from},#{pageSize}
    </select>

    <select id="getProList" resultType="provider">
        select * from smbms.smbms_provider
    </select>

    <select id="getProviderCount" resultType="int">
        select count(1) from smbms.smbms_provider
        <where>
        <if test="proName != null">
             proName like "%"#{proName}"%"
        </if>
        <if test="proCode != null">
            and proCode = #{proCode}
        </if>
    </where>
    </select>

    <delete id="deleteProviderById" >
        delete from smbms.smbms_provider where id = #{id}
    </delete>

    <select id="getProviderById" resultType="provider">
        select * from smbms.smbms_provider where id = #{id}
    </select>

    <update id="modify" >
        update smbms.smbms_provider set id = #{id}, proCode = #{proCode}, proName = #{proName}, proDesc =  #{proDesc},
                                        proContact = #{proContact}, proPhone = #{proPhone},proAddress =  #{proAddress},
                                        proFax = #{proFax}, createdBy = #{createdBy}, creationDate = #{creationDate},
                                        modifyDate = #{modifyDate}, modifyBy = #{modifyBy} where id = #{id}
    </update>

</mapper>

Provider测试类

package com.jiuqi.dao;

import com.jiuqi.dao.provider.ProviderMapper;
import com.jiuqi.pojo.Provider;
import com.jiuqi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

public class ProviderMapperTest {

    @Test
    public void add() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
        HashMap map = new HashMap();
        map.put("id",16);
        map.put("proCode","JQ_GYS007");
        map.put("proName","善感批发");
        map.put("proDesc","长期合作伙伴,主营产品:百事可乐、小麦果汁、苹果、生活消费品");
        map.put("proContact","韩驰");
        map.put("proPhone","13796942060");
        map.put("proAddress","北京市通州区");
        map.put("proFax","0523-21299123");
        map.put("createdBy",1);
        map.put("creationDate",new Date());
        mapper.add(map);


        sqlSession.close();
    }

    @Test
    public void getProviderList() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
        HashMap map = new HashMap();
        map.put("proName","善感");
        map.put("proCode","JQ_GYS007");
        map.put("from",0);
        map.put("pageSize",9);
        List<Provider> providerList = mapper.getProviderList(map);
        for (Provider provider : providerList) {
            System.out.println(provider);
        }


        sqlSession.close();
    }

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

        sqlSession.close();
    }

    @Test
    public void getProviderCount() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
        int count = mapper.getProviderCount("善感", "JQ_GYS007");
        System.out.println(count);

        sqlSession.close();

    }

    @Test
    public void deleteProviderById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
       mapper.deleteProviderById(16);

        sqlSession.close();

    }

    @Test
    public void getProviderById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
        Provider providerById = mapper.getProviderById(16);
        System.out.println(providerById);

        sqlSession.close();

    }

    @Test
    public void modify() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ProviderMapper mapper = sqlSession.getMapper(ProviderMapper.class);
        HashMap map = new HashMap();
        map.put("id",16);
        map.put("proCode","JQ_GYS007");
        map.put("proName","善感批发");
        map.put("proDesc","长期合作伙伴,主营产品:百事可乐、小麦果汁、苹果、生活消费品");
        map.put("proContact","嘿嘿");
        map.put("proPhone","13796942060");
        map.put("proAddress","北京市朝阳区");
        map.put("proFax","0523-21299123");
        map.put("createdBy",1);
        map.put("creationDate",new Date());
        mapper.modify(map);

        sqlSession.close();

    }

}

3.Role

 Role实体类

package com.jiuqi.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class Role {
    private Integer id;   //id
    private String roleCode; //角色编码
    private String roleName; //角色名称
    private Integer createdBy; //创建者
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者
    private Date modifyDate;//更新时间

}

RoleMapper

package com.jiuqi.dao.role;

import com.jiuqi.pojo.Role;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface RoleMapper {
    //获取角色列表
    public List<Role> getRoleList();

    //增加角色信息
    public int add(Role role);

    //通过Id删除Role
    public int deleteRoleById(@Param("id") Integer delId);

    //修改角色信息
    public int modify(Map map);

    //通过Id获取role
    public Role getRoleById(@Param("id") Integer id);

    //根据roleCode,进行角色编码的唯一性验证
    public int roleCodeIsExist(@Param("roleCode") String roleCode);

}

RoleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiuqi.dao.role.RoleMapper">

    <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

    <select id="getRoleList" resultType="role">
        select * from smbms.smbms_role
    </select>

    <insert id="add">
        insert into smbms.smbms_role(id, roleCode, roleName, createdBy, creationDate, modifyBy, modifyDate)
        values (#{id}, #{roleCode}, #{roleName}, #{createdBy}, #{creationDate}, #{modifyBy}, #{modifyDate})
    </insert>

    <delete id="deleteRoleById">
        delete from smbms.smbms_role where id = #{id}
    </delete>

    <update id="modify" parameterType="map">
        update smbms.smbms_role set id = #{id}, roleCode = #{roleCode}, roleName = #{roleName}, createdBy = #{createdBy},
                                  creationDate = #{creationDate}, modifyBy = #{modifyBy}, modifyDate = #{modifyDate}
                                  where id = #{id}
    </update>

    <select id="getRoleById" resultType="role">
        select * from smbms.smbms_role where id = #{id}
    </select>

    <select id="roleCodeIsExist" resultType="int">
        select count(1) from smbms.smbms_role where roleCode = #{roleCode}
    </select>


</mapper>

Role测试类

package com.jiuqi.dao;


import com.jiuqi.dao.role.RoleMapper;
import com.jiuqi.pojo.Role;
import com.jiuqi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

public class RoleMapperTest {

    @Test
    public void getRoleList() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        List<Role> roleList = mapper.getRoleList();
        for (Role role : roleList) {
            System.out.println(role);
        }

        sqlSession.close();
    }

    @Test
    public void add() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        Role role = new Role();
        role.setId(4);
        role.setRoleCode("SMBMS_JQDS");
        role.setRoleName("总监");
        role.setCreatedBy(1);
        role.setCreationDate(new Date());
        mapper.add(role);

        sqlSession.close();
    }

    @Test
    public void deleteRoleById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        mapper.deleteRoleById(4);

        sqlSession.close();
    }

    @Test
    public void modify() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        HashMap map = new HashMap();
        map.put("id",4);
        map.put("roleCode","SMBMS_JQDS");
        map.put("roleName","产品经理");
        try {
            map.put("creationDate",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-09-07 14:26:34"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        mapper.modify(map);

        sqlSession.close();
    }

    @Test
    public void getRoleById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        System.out.println(mapper.getRoleById(4));

        sqlSession.close();
    }

    @Test
    public void roleCodeIsExist() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
        int code = mapper.roleCodeIsExist("SMBMS_JQDS");
        System.out.println(code);

        sqlSession.close();
    }
}

 4.User

  User实体类

package com.jiuqi.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class User {
    private Integer id; //id
    private String userCode; //用户编码
    private String userName; //用户名称
    private String userPassword; //用户密码
    private Integer gender;  //性别
    private Date birthday;  //出生日期
    private String phone;   //电话
    private String address; //地址
    private Integer userRole;    //用户角色
    private Integer createdBy;   //创建者
    private Date creationDate; //创建时间
    private Integer modifyBy;     //更新者
    private Date modifyDate;   //更新时间
    private Integer age;//年龄
    private String userRoleName;    //用户角色名称

}

UserMapper

package com.jiuqi.dao;

import com.jiuqi.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    //通过userCode获取User
    public User getLoginUser(@Param("userCode") String userCode);

    //增加用户信息
    public int add(Map<String,Object> map);

    //通过条件查询userList
    public List<User> getUserList(@Param("userName") String userName,
                                  @Param("userRole") Integer userRole,
                                  @Param("from") Integer from,
                                  @Param("pageSize") Integer pageSize);

    //通过条件查询-用户记录数
    public int getUserCount(@Param("userName") String userName,
                            @Param("userRole") Integer userRole);

    //通过userId删除user
    public int deleteUserById(@Param("id") Integer id);

    //通过useId获取user
    public User getUserById(@Param("id") Integer id);

    //修改用户信息
    public int modify(Map map);

    //修改当前用户密码
    public int updatePwd(@Param("id") Integer id, @Param("pwd") String pwd);

}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jiuqi.dao.UserMapper">

    <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

    <select id="getLoginUser" resultType="user">
        select * from smbms.smbms_user where userCode = #{userCode}
    </select>

    <insert id="add">
        insert into smbms.smbms_user(id, userCode, userName, userPassword, gender, birthday, phone,
                                     address, userRole, createdBy, creationDate, modifyBy, modifyDate)
                                    values(#{id}, #{userCode}, #{userName}, #{userPassword}, #{gender}, #{birthday}, #{phone},
                                           #{address}, #{userRole}, #{createdBy}, #{creationDate}, #{modifyBy}, #{modifyDate})
    </insert>

    <select id="getUserList" resultType="user">
        select u.*,r.roleName from smbms.smbms_user u,smbms.smbms_role r where u.userRole = r.id
        <if test="userName != null">
            and userName = #{userName}
        </if>
        <if test="userRole != null">
            and userRole = #{userRole}
        </if>
        limit #{from},#{pageSize}
    </select>

    <select id="getUserCount" resultType="int">
        select count(1) from smbms.smbms_user
         <where>
             <if test="userName != null">
                  userName = #{userName}
             </if>
             <if test="userRole != null">
                 and userRole = #{userRole}
             </if>
         </where>
    </select>

    <delete id="deleteUserById">
        delete from smbms.smbms_user where id = #{id}
    </delete>

    <select id="getUserById" resultType="user">
        select * from smbms.smbms_user where id = #{id}
    </select>

    <update id="modify">
    update smbms.smbms_user set id = #{id}, userCode = #{userCode}, userName = #{userName}, userPassword = #{userPassword},
                              gender = #{gender}, birthday = #{birthday}, phone = #{phone}, address = #{address},
                              userRole = #{userRole}, createdBy = #{createdBy}, creationDate = #{creationDate}, modifyBy = #{modifyBy},
                        modifyDate = #{modifyDate} where id = #{id}
    </update>



    <update id="updatePwd">
        update smbms.smbms_user set serPassword = #{pwd} where id = #{id}
    </update>


</mapper>

User测试类

package com.jiuqi.dao;

import com.jiuqi.pojo.User;
import com.jiuqi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

public class UserMapperTest {
    @Test
    public void getLoginUser() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.getLoginUser("admin"));

        sqlSession.close();
    }

    @Test
    public void add() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("id",97);
        map.put("userCode","fei");
        map.put("userName","飞");
        map.put("userPassword","999777");
        map.put("gender",1);
        try {
            map.put("birthday",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2022-03-04 22:32:11"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        map.put("phone","13781588666");
        map.put("address","江西省南昌市");
        map.put("userRole",1);
        map.put("createdBy",1);
        map.put("creationDate",new Date());
        mapper.add(map);

        sqlSession.close();
    }

    @Test
    public void getUserList() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUserList("邓超",null,0,9);
        sqlSession.close();
    }
    @Test
    public void getUserCount() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.getUserCount("邓超",null);
        sqlSession.close();
    }

    @Test
    public void deleteUserById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUserById(97);
        sqlSession.close();
    }

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

    @Test
    public void modify() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap map = new HashMap();
        map.put("id",97);
        map.put("userCode","fei");
        map.put("userName","飞");
        map.put("userPassword","999666");
        map.put("gender",1);
        try {
            map.put("birthday",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2022-03-04 22:32:11"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        map.put("phone","13781588666");
        map.put("address","河南省郑州市");
        map.put("userRole",1);
        map.put("createdBy",1);
        map.put("creationDate",new Date());
        mapper.modify(map);

        sqlSession.close();
    }

    @Test
    public void updatePwd() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updatePwd(97,"123123");
        sqlSession.close();
    }
}

5.核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="db.properties"/>

    <settings>
        <!--标准日志工厂-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>

        <!--显示的开启全局缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--可以给实体类起别名-->
    <typeAliases>
        <package name="com.jiuqi.pojo"/>
    </typeAliases>


    <environments default="development">

        <environment id="development">
            <!--transactionManager事务管理器-->
            <transactionManager type="JDBC"/>
            <!--dataSource数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>

    </environments>


    <mappers>
        <package name="com.jiuqi.dao"/>
    </mappers>

</configuration>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值