Mybatis

 是一个持久层框架

 

环境搭建

在IDEA中新建maven项目

然后在pom.xml添加依赖:

一共添加了三个依赖,mybatis、junit、mysql

复制代码
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>

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

  </dependencies>
复制代码

 

 

 

 

新建模块

建立一个maven模块,然后以项目为父项,在src/main/resources/下新建mybatis-config.xml配置文件

复制代码
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6 <environments default="development">
 7 <environment id="development">
 8 <transactionManager type="JDBC"/>
 9 <dataSource type="POOLED">
10 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
11 <property name="url"
12 value="jdbc:mysql://localhost:3306/mybatis?
13 useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
14 <property name="username" value="root"/>
15 <property name="password" value="123456"/>
16 </dataSource>
17 </environment>
18 </environments>
19 <mappers>
20 <mapper resource="com/darkpar/dao/userMapper.xml"/>
21 </mappers>
22 </configuration>
复制代码

里面需要配置驱动、url、账号密码。

mappers中放的是Dao接口用xml文件的实现类

 

编写Mybatis工具类

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

将这三行代码包装成工具类,得到sql的工厂类。

然后写一个getSession方法,每次调用返回一个sqlSession类对象。

 

里面一共涉及三个对象:

SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory

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

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 

 

工具类的代码:

复制代码
 1 package com.darkpar.utils;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 
11 public class MybatisUtils {
12     private static SqlSessionFactory sqlSessionFactory;
13     static {
14         InputStream inputStream = null;
15         try {
16             String resource = "mybatis-config.xml";
17             inputStream = Resources.getResourceAsStream(resource);
18             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
19 
20         } catch (IOException e) {
21             throw new RuntimeException(e);
22         } finally {
23             if (inputStream!=null) {
24                 try {
25                     inputStream.close();
26                 } catch (IOException e) {
27                     throw new RuntimeException(e);
28                 }
29             }
30         }
31     }
32 
33     public static SqlSession getSqlSession(){
34         return sqlSessionFactory.openSession();
35     }
36 
37 }
复制代码

0827更新:

不需要手动关闭流,mybatis低层给关闭了,所以不需要再finally了

然后

return sqlSessionFactory.openSession(true);

这样可以返回一个自动提交事物的sqlsession

btw,秦疆是真的辣鸡,听不下去了,换了杨博超,好多了,逻辑清晰,不瞎逼逼

 

编写实体类

public class User {
    private int id;
    private String name;
    private String pwd;
}

这个类的数据格式包括变量的命名都要跟数据库中的名一模一样。

 

编写Mapper接口

复制代码
package com.darkpar.dao;

import com.darkpar.pojo.User;

import java.util.List;

public interface UserDao {
    List<User> getUserList();
}
复制代码

 

在接口同路径下编写Mapper.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.darkpar.dao.UserDao">
    <select id="getUserList" resultType="com.darkpar.pojo.User">
        select * from t_user
    </select>
</mapper>
复制代码

这个配置文件就相当于一个实现类,并且需要在前面的mybatis-config.xml的<mappers>中添加上

 

编写测试类

复制代码
package com.darkpar.dao;

import com.darkpar.pojo.User;
import com.darkpar.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 = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();

    }
}
复制代码

 

逻辑整理

执行过程:

在mybatis-config.xml文件有关于数据库的配置,工具类中的静态代码块,在类加载过程中从配置文件拿到sqlSessionFactory,这个过程用到了mybatis的Resources工具类

然后就可以用自己写的工具类拿到sqlSession对象。

又因为session对象是用这个配置文件拿到的,里面也包含了mapper的信息,所以可以拿到接口类对应的mapper。这里在mapper配置文件中的namespace上进行标记了,里面的<select>中实现接口类中的方法,进行查询,并且在<select>resultType属性中指定了返回结果的数据结构。

待测试:如果有多个接口的实现类如何创建。

20220826 更新:

不会有多个类,貌似多个xml文件namespace可以写同一个接口,但是在同namespace下,每个函数只能实现一次,所以不会有重复的问题。

 

通过工具类在总配置文件内拿工厂,拿到session,从session拿到mapper。