JDBC 和 MyBatis

JDBC,是一种 SUN 为统一数据库访问而制定的接口规范。数据库厂商只要实现该接口,Java 层就可以通过该接口访问、管理数据库。它们之间,通过 桥接模式 (事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化) 实现数据访问。

MyBatis 是 ORM(Object/Relational Mapping,对象-关系映射) 框架。其插入在 JDBC 和应用程序之间完成了对数据库操作的封装,但是同时,由于其支持定制化 SQL。

JDBC

JDBC Driver 是 JDBC API 的具体实现。应用直接通过 API ,间接通过驱动完成和数据库之间的交互。

在 JDBC API 中,主要包括以下几个对象:

  • DataSource:代表着可以连接物理数据源的工厂(A factory for connections to the physical data source that this DataSource object represents. )。该接口,通常由数据库厂商实现。

    1
    2
    3
    4
    public interface DataSource  extends CommonDataSource, Wrapper {
    Connection getConnection() throws SQLException;
    Connection getConnection(String username, String password) throws SQLException;
    }
  • Connection:控制和数据库之间的连接。 SQL statements are executed and results are returned within the context of a connection.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface Connection  extends Wrapper, AutoCloseable {
    Statement createStatement() throws SQLException;
    PreparedStatement prepareStatement(String sql) throws SQLException;
    CallableStatement prepareCall(String sql) throws SQLException;
    void commit() throws SQLException;
    void rollback() throws SQLException;
    void close() throws SQLException;
    ......
    }
  • Statement:用于执行静态 SQL 语句,并返回结果。

    1
    2
    3
    4
    5
    6
    7
    8
    public interface Statement extends Wrapper, AutoCloseable {
    ResultSet executeQuery(String sql) throws SQLException;
    int executeUpdate(String sql) throws SQLException;
    oid close() throws SQLException;
    void addBatch( String sql ) throws SQLException;
    int[] executeBatch() throws SQLException;
    ......
    }
  • PreparedStatement:继承了 Statement,代表了一个预编译的 SQL 语句。预编译的语句被存储在 PreparedStatement 中,可以被多次使用。

    1
    2
    3
    4
    5
    6
    7
    public interface PreparedStatement extends Statement {
    ResultSet executeQuery() throws SQLException;
    void setShort(int parameterIndex, short x) throws SQLException;
    void setObject(int parameterIndex, Object x) throws SQLException;
    boolean execute() throws SQLException;
    ......
    }

    使用示例:

    1
    2
    3
    4
    5
    6
    7
    Class.forName("com.mysql.jdbc.Driver");
    connection = DriverManager.getConnection(url,user,password);
    String sql = "update user set username=? where id = ?";
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    preparedStatement.setString(1,"Fant.J");
    preparedStatement.setInt(2,27);
  • CallableStatement:CallableStatement 支持调用存储过程,提供了对输入/输出参数的支持。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface CallableStatement extends PreparedStatement {
    void registerOutParameter(int parameterIndex, int sqlType) throws SQLException;
    void setByte(String parameterName, byte x) throws SQLException;
    void setString(String parameterName, String x) throws SQLException;
    void setBlob (String parameterName, Blob x) throws SQLException;
    void setBinaryStream(String parameterName, java.io.InputStream x,
    long length) throws SQLException;
    ......
    }
  • ResultSet:Statement 执行完的结果集。

    1
    2
    3
    4
    5
    6
    public interface ResultSet extends Wrapper, AutoCloseable {
    boolean next() throws SQLException;
    String getString(int columnIndex) throws SQLException;
    boolean getBoolean(int columnIndex) throws SQLException;
    ......
    }

MyBatis

MyBaits 是一个基于 SqlSessionFactory 构建的支持定制化 SQL、存储过程以及高级映射的持久层框架。
对于 SqlSessionFactory 而言,它的作用是生成 SqlSession 接口对象,这个接口对象(单例保持在 MyBatis 框架中)是 MyBatis 操作的核心。

配置

SqlSessionFactory 是通过 Configuration 完成配置的。而 Configuration 的配置,实际上是通过配置文件(比如 application.properties)进行。


(图片来源《深入浅出SpringBoot 2.x》)
可配置项如上所示:

  • ****properties(属性)****:属性文件一般采用 Spring 进行配置。

    1
    2
    3
    4
    5
    spring.datasource.url=jdbc:mysql://localhost:3310/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    ......
  • ****settings(设置)****:该配置将改变 MyBatis 底层行为,可以配置映射规则,如自动映射和驼峰映射、执行器类型、缓存等内容。更多设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。
    mybatis.configuration.lazy-loading-enabled=true
    #使全局的映射器启用或禁用缓存。
    mybatis.configuration.cache-enabled=true
    #配置默认的执行器,可选类型包括 SIMPLE 、REUSE(prepared statements) 、BATCH
    mybatis.configuration.default-executor-type=simple
    #设置本地缓存范围 在默认配置情况下,mybatis会将同一session内的查询结果都放在local cache中,
    #这样可以提高性能,避免每次都hit到数据库
    mybatis.configuration.local-cache-scope=session
    ......
  • ****typeAliases(类型别名)****:由于全限定类名较长,因此,MyBatis会对常用的类提供默认的别名,此外,还允许我们通过 typeAliases 配置自定义的别名。

  • ****typeHandlers(类型处理器)****:在 MyBaits 写入和读取数据库的过程中,对不同类型的数据进行自定义转换。

  • ****Mappers(映射器)****:提供 SQL 和 POJO 映射关系。

核心概念

待补充。。。

在 SpringBoot 中使用 Mybatis(以 MySQL 为例)

添加依赖:

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

在 application.properties 添加基本配置:

1
2
3
4
5
6
7
8
spring.datasource.url=jdbc:mysql://localhost:3310/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.schema=classpath:sql/users.sql
spring.datasource.connectionProperties=classpath:sql/users.sql
spring.datasource.initialization-mode=always
......

设置扫描:

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@MapperScan("com.yuegs.mybatis.mapper")
public class MybatisTestApplication {

public static void main(String[] args) {
SpringApplication.run(MybatisTestApplication.class, args);
}

}

设置 Mapper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.yuegs.mybatis.mapper;

import com.yuegs.mybatis.enu.UserSexEnum;
import com.yuegs.mybatis.model.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface UserMapper {

@Select("SELECT * FROM users")
@Results({
@Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class),
@Result(property = "nickName", column = "nick_name")
})
List<User> getAll();

@Select("SELECT * FROM users WHERE id = #{id}")
@Results({
@Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class),
@Result(property = "nickName", column = "nick_name")
})
User getOne(Long id);

@Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})")
void insert(User user);

@Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}")
void update(User user);

@Delete("DELETE FROM users WHERE id =#{id}")
void delete(Long id);

}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   @Autowired
private UserMapper userMapper;

@Autowired
DataSource dataSource;

@Test
public void testInsert() throws Exception {
System.out.println("获取的数据库连接为:"+dataSource.getConnection());
userMapper.insert(new User("aa1", "a123456", UserSexEnum.MAN));
userMapper.insert(new User("bb1", "b123456", UserSexEnum.WOMAN));
userMapper.insert(new User("cc1", "b123456", UserSexEnum.WOMAN));
System.out.println("size -=------------------->"+userMapper.getAll().size());
}

MyBatis 和 JDBC 的关联

可以看到,MyBatis 和 JDBC 之间有很多相似概念。MyBatis 使得 JDBC 的操作更加方便、快捷、灵活,如下图示,以后有空看完 MyBatis 源码后再做补充。

(图片来源)


参考文档:
Database Access (MyBatis3)
秒懂设计模式之桥接模式(Bridge Pattern)
How Does JDBC Work?
JDBC数据源(DataSource)的简单实现
执行对象Statement、PreparedStatement和CallableStatement详解 JDBC简介(五)
JDBC(五)PreparedStatement 详解
聊聊MyBatis缓存机制
MyBatis 核心配置综述之 Configuration 详解
从mybatis到mybatis-spring-boot-starter
MyBatis SQL是如何执行的?

© 2024 YueGS