Mybatis笔记

一、Mybatis简绍

1、Mybatis简单介绍

Mybatis是一款持久层(dao层)框架,支持自定义 SQL、存储过程以及高级映射(简化了java代码对数据库的操作),MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作,通过xml和注解映射java对象和接口为数据库中的记录。



2、Mybatis的特点

①简单易学.
②灵活.
③sql和代码分离,提高了可维护性.
④提供了映射标签支持对象与数据库字段关系映射.
⑤提供了xml标签是我们方便编写动态sql.



二、Mybatis入门程序

①创建数据库
在这里插入图片描述
②使用IDEA创建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>mybatis-study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>mybatis-demo01</module>
    </modules>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
        <!--mybatis依赖-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <!--junit依赖-->
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

③创建Mybatis-config.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置环境-->
<configuration>
    <!--默认的环境-->
    <environments default="development">
        <environment id="development">
            <!--使用的事jdbc的事务管理-->
            <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="19990704"/>
            </dataSource>
        </environment>
    </environments>

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


④创建实体类

package com.zhou.pojo;

public class User {
    private Integer id;
    private String username;
    private String password;

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

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

⑤创建接口和UserMapper.xml配置文件

package com.zhou.dao;

import com.zhou.pojo.User;

import java.util.List;

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

<?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" >
<!--绑定dao层接口,用于映射dao层方法,namespace=“类的全限定名”-->
<mapper namespace="com.zhou.dao.UserDao">

    <!--id="dao层接口方法名" resultType=“返回全限定名”-->
    <select id="findUser" resultType="com.zhou.pojo.User">
        select * from t_user
    </select>

</mapper>

⑥创建Mybatis工具类读取配置文件信息.

package com.zhou.util;

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;

public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    static {
      try {
          //通过流加载配置文件
          InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
          //创建sqlsession对象
         sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
      }catch (IOException e){
          e.printStackTrace();
      }
    }

    /*打开会话对象*/
    public static SqlSession getSqlSession () {
    //增删改查需要开启自动提交事务
        return sqlSessionFactory.openSession(true);
    }


}

⑦测试查询用户方法

在这里插入图片描述

三、使用Mybatis进行CRUD

dao

public interface UserDao {
    //查询
     List<User> findUser();
    //添加用户
    Integer saveUser(User user);
    //删除用户
    Integer deleteUserById(User user);
    //修改用户
    Integer updateUserById(User user);
}

UserMapper
注意:在Mybatis使用 #{} 为参数占位符 ?,即sql 预编译
${} 为字符串替换,即 sql 拼接.

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--绑定dao层接口,namespace=“类的全限定名”-->
<mapper namespace="com.zhou.dao.UserDao">

    <!--id="dao层接口方法名" resultType=“返回全限定名”-->
    <!--查询-->
    <select id="findUser" resultType="com.zhou.pojo.User">
        select * from t_user
    </select>
    <!--添加  参数的类型parameterType="com.zhou.pojo.User"-->
    <insert id="saveUser" parameterType="com.zhou.pojo.User">
        insert into t_user (username,password) values (#{username},#{password})
    </insert>
    <!--删除-->
    <delete id="deleteUserById" parameterType="com.zhou.pojo.User">
        delete from t_user where id = #{id}
    </delete>
    <!--修改-->
    <update id="updateUserById" parameterType="com.zhou.pojo.User">
        update t_user set username=#{username},password=#{password} where id=#{id}
    </update>
</mapper>

四、Mybatis执行原理

在这里插入图片描述

五、 万能Map多条件和模糊查询

dao

 //使用根据用户名和密码查询用户
    User findUserByUsernameAndPassword(Map<String, Object> map);

    //模糊查询
    List<User> findUserByLike(Map<String,Object> map);

UserMapper

 <!--根据账户密码查询用户-->
    <select id="findUserByUsernameAndPassword" parameterType="Map" resultType="com.zhou.pojo.User">
        select * from t_user where username=#{username} and password=#{password}
    </select>

    <!--模糊查询-->
    <select id="findUserByLike" parameterType="Map" resultType="com.zhou.pojo.User">
        select * from t_user where username like concat('%',#{username},'%')
    </select>
 @Test
    public void testFindUser() {
        //获得sqlsession
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        //获得mapper执行sql
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> user = userDao.findUser();
        for (User user1 : user) {
            System.out.println(user1);
        }
        sqlSession.close();
    }

    //测试添加
    @Test
    public void testSaveUser() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserDao us = sqlSession.getMapper(UserDao.class);
        User user = new User(0, "小明", "6666");
        Integer add = us.saveUser(user);
        System.out.println(add > 0 ? "添加成功" : "添加失败");
        sqlSession.close();
    }

    //测试删除
    @Test
    public void testDeleteUserById() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserDao us = sqlSession.getMapper(UserDao.class);
        User user = new User();
        user.setId(1);
        Integer de = us.deleteUserById(user);
        System.out.println(de>0?"删除成功":"删除失败");
        sqlSession.close();

    }

    //修改
    @Test
    public void testUpdateuserById () {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserDao us = sqlSession.getMapper(UserDao.class);
        User user = new User();
        user.setId(2);
        user.setUsername("李四");
        user.setPassword("55555");
        Integer update = us.updateUserById(user);
        System.out.println(update>0?"修改成功":"修改失败");
        sqlSession.close();
    }



六、Mybatis配置

6.1、配置别名

在Mybatis核心配置文件加入代码,在UserMapper.xml里面**resultType=“User”**可以不要写全限定名,写类名就行.

 <!--配置别名-->
    <typeAliases>
        <package name="com.zhou.pojo"/>
    </typeAliases>

6.2、配置驼峰命名

配置驼峰命名,例如数据库字段user_name映射到实体类属性userName .
注意:要开启驼峰命命名匹配才能将数据库字段与实体类属性进行映射.

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

6.3、配置映射器

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

6.4、配置log4j

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息的输出.
使用方法
导入依赖

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

在resource下创建log4j.properties文件

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/zhou.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

mybatis配置文件开启log4j日志

    <settings>
        <!--配置login4j-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

输出结果
在这里插入图片描述



6.5配置lombok

使用lombok实体类不需要写构造方法和tostring以及get、set方法.
使用方法
导入依赖

 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
        <scope>provided</scope>
    </dependency>

实体类

package com.zhou.pojo;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
}



七、生命周期和作用域

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

7.1、SqlSessionFactoryBuilder

因为是局部变量一旦创建了 SqlSessionFactory,就不再需要它了.

7.2、SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”,SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式.

7.3、SqlSession

SqlSession用于打开会话,相当于建立与数据库之间的桥梁,SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中.

实例

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // 你的应用逻辑代码
}

八、 ResultMap

ResultMap是Mybatis强大的一个功能,主要用来解决数据库字段与实体类属性不一致的情况,可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

dao

List<User> findUser();

UserMapper

resultMap="UserMap"用于关联下面的resultMap,id为主键 ,result结果集column字段为数据库的字段,property为实体类的属性.

<mapper namespace="com.zhou.dao.UserDao">
    <select id="findUser" resultMap="UserMap">
        select * from t_user
    </select>
    <resultMap id="UserMap" type="User">
        <id property="id" column="id"/>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
    </resultMap>
</mapper>

在这里插入图片描述



九、Mybatis分页查询

9.1、使用imit进行分页

dao

 //分页查询
    List<User> findUserByLimit(Map<String,Object> map);

UserMapper.xml

<!--分页查询-->
    <select id="findUserByLimit" resultType="com.zhou.pojo.User" parameterType="Map">
        select * from t_user limit #{startIndex},#{pageSize}
    </select>

运行结果
在这里插入图片描述

9.2、使用RowBounds进行分页

dao

List<User> findUserByRowBounds();

UserMapper.xml

<select id="findUserByRowBounds" resultType="com.zhou.pojo.User">
        select * from t_user
    </select>

测试类代码

 //RowBounds分页查询
    @Test
    public void findUserByRowBounds () {
        //获得sqlsession
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        RowBounds rowBounds = new RowBounds(1,2);
        List<User> userList = sqlSession.selectList("com.zhou.dao.UserDao.findUserByRowBounds",null,rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

输出结果
在这里插入图片描述

9.3、使用PageHelp进行分页

dao

  //查询
     List<User> findUser();

导入依赖

 <select id="findUser" resultMap="UserMap">
        select * from t_user
    </select>

配置分页插件

 <!--配置分页插件-->
    <plugins>
        <!-- com.github.pagehelper为PageHelper类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 方言 -->
            <property name="dialect" value="mysql"/>
            <!-- 该参数默认为false -->
            <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
            <property name="rowBoundsWithCount" value="true"/>
        </plugin>
    </plugins>

测试类

 @Test
    public void findUser () {
        //获得sqlsession
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserDao us = sqlSession.getMapper(UserDao.class);
        //开启分页,1为当前页,2为每页大小
        PageHelper.startPage(1,2);
        List<User> userList = us.findUser();
        //PageInfo指定分页对象为User把查询结果集合放到pageinfo里面
        PageInfo<User> pageInfo = new PageInfo<User>(userList);
        for (User user : pageInfo.getList()) {
            System.out.println(user);
        }
        sqlSession.close();
    }


十、使用注解进行CRUD

pom依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>
    <!--mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--junit依赖-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.4.2</version>
    </dependency>
    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>

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

核心配置文件

	<mappers>
        <mapper class="com.zhou.dao.UserDao"/>
    </mappers>

dao

package com.zhou.dao;

import com.zhou.pojo.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;
import java.util.Map;

public interface UserDao {
    //查询
     @Select("select * from t_user")
     List<User> findUser();
     //修改
    @Update("update t_user set username=#{username},password=#{password} where id=#{id}")
    Integer updateUser (User user);
    //删除
    @Delete("delete from t_user where id=#{id}")
    Integer deleteUserById(Integer id);
    //添加
    @Insert("insert into t_user(username,password) values(#{username},#{password})")
    Integer addUser (User user);
}

测试

 //测试添加
    @Test
    public void addUser() {
        //获得sqlsession
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        //获得mapper执行sql
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        User user = new User(0,"李四","666666");
        Integer update = userDao.addUser(user);
        System.out.println(update>0?"添加成功":"添加失败");
    }


十一、Mybatis 关系映射

11.1、准备工作

创建数据表

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 (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');

创建实体类
我这里使用的是lombok工具类所以不用写构造、getset以及tostring方法.
学生表

package com.zhou.pojo;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private Integer tid;
    //学生关联老师(多对一关系)
    private Teacher teacher;
}

教师类

package com.zhou.pojo;

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

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private Integer id;
    private String name;
    //一个老师关联多个学生,一对多关系
    private List<Student> students;
}

pom依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>
    <!--mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--junit依赖-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.4.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>

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

mybatis核心配置文件

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


<!--配置驼峰命名 例如数据库字段字段user_name对应映射到实体类属性userName -->
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--配置别名-->
<typeAliases>
    <package name="com.zhou.pojo"/>
</typeAliases>
<!--配置分页插件-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <!-- 方言 -->
        <property name="dialect" value="mysql"/>
        <!-- 该参数默认为false -->
        <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
        <property name="rowBoundsWithCount" value="true"/>
    </plugin>
</plugins>
<!--默认的环境-->
<environments default="development">
    <environment id="development">
        <!--使用的事jdbc的事务管理-->
        <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="19990704"/>
        </dataSource>
    </environment>
</environments>

<mappers>
    <mapper resource="mapper/StudentMapper.xml"/>
    <mapper resource="mapper/TeacherMapper.xml"/>
</mappers>

</configuration>

Mybatis用来描述关系映射的复杂属性需要单独处理,如果是对象使用association,集合使用collection.

11.1、一对多

用学生和老师来进行举例子,多个学生对应一个老师,我们称之为一对多关系.
一对多的关系在教师实体类加private List<Student> students;因为学生十多个所以返回类型为集合.
在这里插入图片描述接下来编写dao层接口

package com.zhou.dao;

import com.zhou.pojo.Teacher;
import org.apache.ibatis.annotations.Param;
public interface TeacherMapper {
	//@Param("tid")为你传的参数,在mapper.xml里面使用#{传的参数名}
    Teacher findTeacher(@Param("tid") Integer tid);
}

TacherMapper.xml

<?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.zhou.dao.TeacherMapper">
    <!--根据老师的id查询下面所有的学生-->
    <select id="findTeacher" resultMap="TeacherAndStudent">
        SELECT s.id sid,s.name sname,t.id tid,t.name tname FROM teacher t,student s WHERE t.id=#{tid}
    </select>

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

</mapper>

运行结果
在这里插入图片描述

11.2、多对一

多个学生对应一个老师称之为多对一关系,描述多对一关系在学生实体类里面加private Teacher teacher;.
在这里插入图片描述
dao层接口

package com.zhou.dao;

import com.zhou.pojo.Student;

import java.util.List;

public interface StudentMapper {
    List<Student> findStudent();

    List<Student> findStudent2(Integer tid);
}
package com.zhou.dao;

import com.zhou.pojo.Student;

import java.util.List;

public interface StudentMapper {
    List<Student> findStudent();

    List<Student> findStudent2(Integer tid);
}

StudentMapper.xml

<?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.zhou.dao.StudentMapper">

    <!--多以一查询结果处理-->
    <select id="findStudent2" resultMap="StudentAndTeacher2" parameterType="integer">
        SELECT s.*,t.name tname FROM student s,teacher t WHERE s.tid=#{id}
    </select>

    <resultMap id="StudentAndTeacher2" type="Student">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="tid" property="tid"/>
        <!--复杂的属性我们需要单独处理,如果是对象使用association,集合使用collection-->
        <association property="teacher" javaType="Teacher">
            <id column="id" property="id"/>
            <result column="tname" property="name"/>
        </association>
    </resultMap>

    <!--首先查询出来student的信息再根据student的tid查询对应的teacher信息-->
    <select id="findStudent" resultMap="StudentAndTeacher">
        select * from student
    </select>
    <resultMap id="StudentAndTeacher" type="Student">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--复杂的属性我们需要单独处理,如果是对象使用association,集合使用collection-->
        <association property="teacher" column="tid" javaType="Teacher" select="findTeacher"/>
        
    </resultMap>
    <select id="findTeacher" resultType="Teacher">
        select * from teacher where id=#{id}
    </select>
</mapper>

运行结果
在这里插入图片描述



十二、动态SQL

动态sql是Mybatis的强大特性之一,动态sql可以根据不同的条件生成不同的sql语句,解决了sql拼接的痛苦.
准备工作
pom依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>
    <!--mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--junit依赖-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.4.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>

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

核心配置文件

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


    <!--配置驼峰命名 例如数据库字段字段user_name对应映射到实体类属性userName -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--配置login4j-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <!--配置别名-->
    <typeAliases>
        <package name="com.zhou.pojo"/>
    </typeAliases>
    <!--配置分页插件-->
    <plugins>
        <!-- com.github.pagehelper为PageHelper类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 方言 -->
            <property name="dialect" value="mysql"/>
            <!-- 该参数默认为false -->
            <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
            <property name="rowBoundsWithCount" value="true"/>
        </plugin>
    </plugins>
    <!--默认的环境-->
    <environments default="development">
        <environment id="development">
            <!--使用的事jdbc的事务管理-->
            <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="19990704"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
<!--        <mapper resource="com/zhou/dao/UserMapper.xml"/>-->
        <mapper class="com.zhou.dao.BlogMapper"/>
    </mappers>

</configuration>

连接工具类

package com.zhou.util;

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;

public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    static {
      try {
          //通过流加载配置文件
          InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
          //创建sqlsession对象
         sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
      }catch (IOException e){
          e.printStackTrace();
      }
    }

    /*打开会话对象*/
    public static SqlSession getSqlSession () {
        //设置为自动提交事务
        return sqlSessionFactory.openSession(true);
    }


}

UUID工具类

package com.zhou.util;

import java.util.UUID;

@SuppressWarnings("all")
public class IDutils {
    public static String getId () {
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    public static void main(String[] args) {
        String id = IDutils.getId();
        System.out.println(id);
    }
}

实体类

package com.zhou.pojo;

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

import java.util.Date;

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

12.1、动态SQL-if

dao

package com.zhou.dao;

import com.zhou.pojo.Blog;
import java.util.List;
import java.util.Map;

public interface BlogMapper {
    Integer addBlog(Blog blog);
    List<Blog> findBlogIf(Map<String,Object> map);
}

BlogMapper.xml
如果标题不为空就拼接 and title=#{title},如果author不等于空 拼接and author=#{author},如果都为空就查询所有.

 <!--条件查询-->
    <select id="findBlogIf" parameterType="Map" resultType="Blog">
        select * from blog 
        <where>
        <if test="title !=null">
             title=#{title}
        </if>
        <if test="author !=null">
            and author=#{author}
        </if>
        </where>
    </select>

12.2、动态SQL-choose、when、otherwis

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用,Mybatis提供了choose元素解决这个问题,choose类似于switch语句.

dao

List<Blog> findBlogChoose(Map<String,Object> map);

BlogMapper.xml
choose类似于switch,when类似于switch下的case,otherwise类似default.

 <select id="findBlogChoose" parameterType="Map" resultType="Blog">
        select * from 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>

12.3、动态SQL-set

dao

 Integer updateBlog(Map<String,Object> map);

BlogMapper.xml
平常进行修改的时候我们都需要set 字段=值多个值之间逗号隔开,而mybatis提供了set元素帮我们去掉逗号.

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

12.4、动态SQL-sql片段和foreach

sql片段就是将公共的sql代码进行提取,mybatis提供sql元素来完成此操作,在条件里面使用<include refid="sql片段id"></include>即可,提高了代码的重用性.
dao

 <sql id="if-title-author">
        <if test="title !=null">
            title=#{title}
        </if>
        <if test="author !=null">
            and author=#{author}
        </if>
    </sql>
    <!--条件查询-->
    <select id="findBlogIf" parameterType="Map" resultType="Blog">
        select * from blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>

结果
在这里插入图片描述
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。

元素名描述
item集合中元素迭代时的别名,该参数为必选
index在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选
openforeach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
separator元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选
closeforeach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选
collection要做遍历的对象

dao

List<Blog> findBlogForeach(Map<String,Object> map);
 <!--foreach使用-->
    <select id="findBlogForeach" parameterType="Map" resultType="Blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>


十三、Mybatis缓存

13.1、简介

缓存是存在内存中的临时数据,用户进行第一次查询后会将数据保存在缓冲中,第二次查询的时候就不需要从磁盘上进行查询,直接从缓存中进行查询,提高了查询效率,解决了高并发系统问题.
好处: 减少和数据库的交互、减少系统开销、提高系统效率.
使用缓存的数据: 经常查询且不经常修改的数据.

13.2、Mybatis缓存

mybatis有一个强大的缓存特性,可以定制和配置缓存,大大的提高了查询效率,Mybatis默认提供了一级缓存二级缓存,一级缓存默认开启(sqlsession级别的缓存,本地缓存),二级缓存需要自己去开启和配置(基于namespace级别的缓存),mybatis提供Cache接口,通过实现Cache接口自定义二级缓存.

13.2.1一级缓存

一级缓存默认开启,只在一次sqlsession中有效.
在这里插入图片描述缓存失效的情况:
①查询不同的数据.
②增删改语句有可能会改变原来的数据会刷新.
③查询不同的Mapper.xml.
④手动清理缓存sqlSession.clearCache();.

13.2.1二级缓存

二级缓存是基于namespace的,也叫一级缓存是因为一级缓存效率太低了所以才诞生了二级缓存.

工作原理
①一个会话查询一条数据,这条数据会放到当前会话的一级缓存中.
②如果会话关闭了对应的一级缓存没了,一级缓存的数据会保存到二级缓存中.
③当有新的会话查询信息会直接从二级缓存进行查询.
④不同的mapper查出的数据会放到对应的缓存中.

使用步骤
①在核心配置文件里面开启全局缓存:<setting name="cacheEnabled " value="true"/>
②在需要使用的mapper.xml中开启<cache/>

③也可以自定义参数
创建了名为 FIFO 缓存,每隔 60 秒刷新,最多存或列表的 512 个引用,而且返回的对象被认为是只读的,

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

13.3、mybatis缓存原理

)

13.4、ehcache自定义缓存

使用方法
导入依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>
    <!--mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--junit依赖-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.4.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>
    <!-- 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>
</dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>



    </build>

在Mapper.xml文件指定使用自定义缓存

 <!--自定义缓存-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
<?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"/>
   <!-- <cache
            name="cloud_user" 缓存名称
            eternal="false" 对象是否永久有效
            maxElementsInMemory="5000" 缓存最大数目
             maxElementsOnDisl:硬盘缓存最大数目
            overflowToDisk="false" 是否保存到磁盘
            timeToIdleSeconds="1800" 设置对象在失效前允许闲置时间(单位:秒)
            timeToLiveSeconds="1800" 设置对在失效后允许存活时间(单位:秒)
            memoryStoreEvictionPolicy="LRU"/> 可选策略 LRU(最近最少使用策略,默认策略)FIFO(先进先出)、LFU(最少访问次数)-->

</ehcache>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值