Mybatis涉及的设计模式

MyBatis 是一种基于 Java 的 ORM(对象关系映射)框架,它并没有明确地使用大量的设计模式,而是借鉴了一些设计模式的思想和实践。以下是 MyBatis 中涉及的一些设计模式:

数据访问对象模式(DAO):

MyBatis 中使用了 DAO 模式来将数据库操作从业务逻辑中分离出来。通过 DAO 接口和相应的实现类,将数据库操作进行封装和管理。下面是一个 MyBatis 数据访问对象(DAO)模式的代码示例:\

DAO代码示例

假设有一个 User 实体类,其属性包括 id、name 和 age。在 MyBatis 中,我们需要创建一个对应的 UserMapper 接口和 UserMapper.xml 文件来实现与数据库的交互。

  1. User 实体类
public class User {
    private int id;
    private String name;
    private int age;

    // 省略 getter 和 setter 方法
}

  1. UserMapper 接口
public interface UserMapper {
    /**
     * 根据用户 ID 查询用户信息
     * @param id 用户 ID
     * @return User 用户信息
     */
    User getUserById(int id);

    /**
     * 添加用户信息
     * @param user 用户信息
     */
    void addUser(User user);

    /**
     * 更新用户信息
     * @param user 用户信息
     */
    void updateUser(User user);

    /**
     * 删除用户信息
     * @param id 用户 ID
     */
    void deleteUser(int id);
}

  1. UserMapper.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.example.mapper.UserMapper">
    <!-- 根据用户 ID 查询用户信息 -->
    <select id="getUserById" parameterType="int" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>

    <!-- 添加用户信息 -->
    <insert id="addUser" parameterType="com.example.entity.User">
        INSERT INTO user (name, age) VALUES (#{name}, #{age})
    </insert>

    <!-- 更新用户信息 -->
    <update id="updateUser" parameterType="com.example.entity.User">
        UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}
    </update>

    <!-- 删除用户信息 -->
    <delete id="deleteUser" parameterType="int">
        DELETE FROM user WHERE id = #{id}
    </delete>
</mapper>

在这个示例中,我们定义了一个 UserMapper 接口和一个 UserMapper.xml 文件。在 UserMapper 接口中,我们定义了一些方法,这些方法对应着数据库中的操作,比如查询用户信息、添加用户信息、更新用户信息和删除用户信息等。在 UserMapper.xml 文件中,我们定义了每个方法对应的 SQL 语句,MyBatis 将根据这些 SQL 语句来执行数据库操作。
使用 MyBatis 的时候,我们只需要注入 UserMapper 接口的实现类即可,然后就可以通过调用 UserMapper 接口中的方法来实现对数据库的操作了。例如:

@Autowired
private UserMapper userMapper;

// 根据用户 ID 查询用户信息
User user = userMapper.getUserById(1);

// 添加用户信息
User newUser = new User();
newUser.setName("xiaobei");
newUser.setAge(23);
userMapper.addUser(newUser);

建造者模式(Builder)

MyBatis 中的配置文件可以使用建造者模式进行构建。例如,通过 XMLConfigBuilder 来构建 SqlSessionFactory 实例。

MyBatis 的配置文件(XML 文件)使用了 Builder 模式具体过程

在 MyBatis 中,XML 配置文件用于定义 SQL 映射以及其他的配置信息。
MyBatis 的配置文件使用了 Builder 模式来创建和配置 SqlSessionFactory 对象。具体的过程如下:

  1. 创建一个 Configuration 对象:在 MyBatis 中,所有的配置信息都存储在 Configuration 对象中,因此我们需要首先创建一个 Configuration 对象。
  2. 配置数据源:在 Configuration 对象中配置数据源的相关信息,包括数据库驱动、连接池、连接字符串等。
  3. 配置类型别名:在 Configuration 对象中配置 Java 类型和 SQL 类型之间的别名映射,以便在 XML 配置文件中使用 Java 类型来代替 SQL 类型。
  4. 配置映射器:在 Configuration 对象中配置映射器,即将 Java 对象和 SQL 语句进行映射的配置信息。映射器可以通过 XML 文件或注解的方式来配置。
  5. 使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory:使用 SqlSessionFactoryBuilder 对象来创建 SqlSessionFactory 对象,同时将 Configuration 对象传递给 SqlSessionFactoryBuilder 对象。
  6. 使用 SqlSessionFactory 获取 SqlSession:通过 SqlSessionFactory 对象来获取 SqlSession 对象,SqlSession 对象用于执行 SQL 语句。

XMLConfigBuilder 来构建 SqlSessionFactory 实例具体过程

MyBatis中的SqlSessionFactory是用于创建SqlSession实例的工厂类。要创建SqlSessionFactory实例,需要使用XML配置文件或Java代码进行配置。下面是使用XML配置文件进行配置的具体过程:

  1. 创建一个XML配置文件。例如,文件名为"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">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydatabase"/>
        <property name="username" value="myuser"/>
        <property name="password" value="mypassword"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="com/example/mapper/UserMapper.xml"/>
  </mappers>
</configuration>

上面的配置文件定义了一个环境(development)和一个数据源(POOLED),以及一个Mapper映射文件。其中,数据源配置中的"driver"、“url”、“username”、"password"属性需要根据实际情况进行修改。

  1. 创建一个XMLConfigBuilder实例。该实例将解析XML配置文件并构建Configuration对象。例如:
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
XMLConfigBuilder configBuilder = new XMLConfigBuilder(inputStream);
Configuration configuration = configBuilder.parse();

  1. 通过Configuration对象构建SqlSessionFactory实例。例如:
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(configuration);

上述代码中,SqlSessionFactoryBuilder()用于创建SqlSessionFactory实例。它需要一个Configuration对象作为参数。Configuration对象包含了MyBatis的所有配置信息,包括数据源配置、类型别名、插件等。
通过以上步骤,就可以创建一个SqlSessionFactory实例,然后使用它来创建SqlSession实例,从而进行数据库操作。例如:

SqlSession session = sessionFactory.openSession();
try {
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = userMapper.selectUserById(1);
    System.out.println(user);
} finally {
    session.close();
}

上述代码中,我们首先通过SqlSessionFactory创建了一个SqlSession实例。然后,使用SqlSession实例获取了一个UserMapper的代理对象,并使用它来查询数据库中的一个用户。最后,记得关闭SqlSession实例。

工厂模式(Factory)

MyBatis 中使用了工厂模式来创建 SqlSession、SqlSessionFactory、SqlSessionFactoryBuilder 等实例。例如,通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例,通过 SqlSessionFactory 创建 SqlSession 实例。

SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例

SqlSessionFactoryBuilder 是 MyBatis 中用于创建 SqlSessionFactory 实例的类。它通过解析 MyBatis 配置文件(mybatis-config.xml)以及 Mapper 映射文件(*.xml)来创建 SqlSessionFactory 实例。具体过程如下:

  1. 首先,SqlSessionFactoryBuilder 会读取 MyBatis 配置文件 mybatis-config.xml,并将其解析为一个 org.apache.ibatis.session.Configuration 对象。
  2. 接着,SqlSessionFactoryBuilder 会读取 Mapper 映射文件(*.xml),并将其解析为一个 org.apache.ibatis.mapping.MappedStatement 对象。MappedStatement 对象中包含了 SQL 语句、参数映射信息、结果集映射信息等。
  3. SqlSessionFactoryBuilder 会将 Configuration 对象中的 MappedStatement 对象和其他属性设置(比如数据库连接池、插件等)与 Mapper 映射文件中的 MappedStatement 对象合并,最终创建一个 SqlSessionFactory 实例。
  4. SqlSessionFactoryBuilder 最后返回 SqlSessionFactory 实例,开发者可以使用该实例创建 SqlSession 对象并执行 SQL 操作。

SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例的过程是读取配置文件、解析配置文件、合并配置信息,并最终创建 SqlSessionFactory 实例的过程。

通过 SqlSessionFactory 创建 SqlSession 实例

SqlSession 是 MyBatis 中用于与数据库交互的核心类,通过 SqlSessionFactory 创建 SqlSession 实例的过程如下:

  1. 首先,开发者需要通过 SqlSessionFactoryBuilder 创建一个 SqlSessionFactory 实例,该实例包含了 MyBatis 的配置信息以及数据库连接信息。
  2. 接着,开发者可以通过 SqlSessionFactory 的 openSession() 方法创建一个 SqlSession 实例。openSession() 方法提供了多个重载形式,可以设置事务级别、是否自动提交事务、执行器类型等。
  3. SqlSessionFactory 会通过创建一个 org.apache.ibatis.session.defaults.DefaultSqlSession 实例来实现 SqlSession 接口,同时将 SqlSession 的配置信息、数据源、事务管理器等信息传递给 DefaultSqlSession。
  4. 在 SqlSession 中,开发者可以通过调用 select、insert、update、delete 等方法执行 SQL 操作,同时 SqlSession 会将 SQL 语句、参数、结果集映射等信息交给 Executor 对象进行执行。
  5. SqlSession 执行 SQL 操作完成后,会将结果返回给开发者,同时释放数据库连接。

通过 SqlSessionFactory 创建 SqlSession 实例的过程就是创建 SqlSession 对象,并将其与配置信息、数据库连接等相关信息绑定在一起。开发者可以通过 SqlSession 对象来执行 SQL 操作,并最终释放数据库连接。

适配器模式(Adapter)

MyBatis 中使用了适配器模式来将各种不同的数据源适配成统一的接口。例如,通过 DataSourceFactory 来创建 DataSource 实例,从而适配各种不同的数据源。

通过 DataSourceFactory 来创建 DataSource 实例

DataSourceFactory 是 MyBatis 中用于创建 DataSource 实例的工厂类,通过它可以创建不同类型的数据源,如 C3P0、Druid、HikariCP 等。创建 DataSource 实例的具体过程如下:

  1. 首先,开发者需要在 MyBatis 的配置文件(mybatis-config.xml)中配置数据源相关的信息,如数据源类型、驱动、URL、用户名、密码等。
  2. 接着,在配置文件中配置 DataSourceFactory 的类型和属性,如下所示:
<dataSource type="com.alibaba.druid.pool.DruidDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</dataSource>

上述代码中,type 属性指定了数据源类型为 DruidDataSource,property 元素指定了该数据源的属性,如驱动、URL、用户名、密码等。

  1. 当 SqlSessionFactoryBuilder 解析配置文件时,会通过 DataSourceFactory 创建 DataSource 实例。首先,它会根据 type 属性的值创建一个 DataSourceFactory 实例。然后,它会调用 DataSourceFactory 的 setProperties() 方法,并将配置文件中的属性设置传递给该方法。DataSourceFactory 实例将根据属性值来创建对应类型的数据源实例。
  2. 最后,SqlSessionFactoryBuilder 将数据源实例设置到 Configuration 对象中,以便后续使用。

通过 DataSourceFactory 创建 DataSource 实例的过程就是读取配置文件中的数据源相关信息、创建 DataSourceFactory 实例、设置属性并创建数据源实例,最终将数据源实例设置到 Configuration 对象中。

动态代理模式(Dynamic Proxy)

MyBatis 中使用了动态代理模式来创建 DAO 接口的实现类。例如,通过 MapperProxyFactory 来创建 MapperProxy 实例,从而代理 DAO 接口的方法调用。
参考:https://blog.csdn.net/Fornewknowledge/article/details/129740798

模板方法模式(Template Method)

MyBatis 中的 SqlSessionTemplate 类使用了模板方法模式来封装和管理数据库操作。例如,通过模板方法 selectOne、selectList 等来执行不同的 SQL 语句。下面是MyBatis中使用模板方法模式进行数据访问的具体过程

  1. 定义抽象模板类

在MyBatis中,定义了一个抽象类BaseExecutor,该类作为执行器的抽象模板,其中包含了一些公共的方法,例如update、query等,以及模板方法doUpdate、doQuery等,具体实现留给子类来完成。

  1. 定义具体子类

MyBatis中有多种不同的执行器,例如SimpleExecutor、ReuseExecutor等,它们都是BaseExecutor的具体子类,负责实现BaseExecutor中的抽象方法。

  1. 实现具体方法

在子类中,实现BaseExecutor中的doUpdate、doQuery等模板方法,完成具体的数据访问操作。例如,在SimpleExecutor中,doUpdate方法会创建一个Statement对象,执行SQL语句,然后返回影响的行数。

  1. 调用模板方法

在应用程序中,通过调用BaseExecutor中的公共方法来执行数据访问操作。这些方法会调用对应的模板方法,然后由子类来实现具体的数据访问操作。例如,调用update方法时,会执行doUpdate方法完成更新操作。
MyBatis使用模板方法模式来实现数据访问操作,将公共的方法放在抽象模板类中,由子类来实现具体的操作,避免了重复代码的产生,提高了代码的可复用性和可维护性。

装饰器模式(Decorator)

MyBatis 中的 SqlSession 对象可以使用装饰器模式来对其进行功能扩展。下面是MyBatis中使用装饰器模式进行功能扩展的具体过程

  1. 定义抽象组件

在MyBatis中,定义了一个抽象接口StatementHandler,该接口定义了一些基本的方法,例如prepare、parameterize等,用于执行SQL语句的操作。

  1. 定义具体组件

MyBatis中包含多种不同的StatementHandler实现,例如RoutingStatementHandler、PreparedStatementHandler等,它们都是StatementHandler接口的具体实现,负责实现StatementHandler中定义的方法。

  1. 定义抽象装饰器

为了能够对StatementHandler进行扩展,需要定义一个抽象装饰器类BaseStatementHandler,该类也实现了StatementHandler接口,并且持有了一个StatementHandler对象的引用,用于将装饰器的操作传递给被装饰对象。

  1. 定义具体装饰器

MyBatis中有多种具体装饰器,例如StatementHandlerInterceptor、ParameterHandlerInterceptor等,它们都是BaseStatementHandler的具体子类,负责实现BaseStatementHandler中定义的方法,并在其中调用被装饰对象的相应方法,完成对StatementHandler的扩展和定制。

  1. 应用装饰器

在MyBatis中,可以通过配置文件或代码方式来应用装饰器,例如可以在配置文件中通过plugins标签来配置具体的装饰器,或者通过InterceptorChain来添加装饰器。
MyBatis使用装饰器模式来实现功能的扩展和定制,通过对抽象组件和具体组件的定义,以及抽象装饰器和具体装饰器的实现,实现了对StatementHandler等核心组件的扩展和定制,提高了框架的灵活性和可扩展性。

通过 TransactionalSqlSessionDecorator 来实现事务的支持

为了支持事务,MyBatis提供了一个名为TransactionalSqlSessionDecorator的装饰器,它可以将SqlSession对象包装成一个支持事务的对象。以下是一个简单的示例代码,演示如何使用TransactionalSqlSessionDecorator来实现事务支持

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class MyBatisService {

    private final SqlSessionTemplate sqlSessionTemplate;

    public MyBatisService(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    public void insertUser(User user) {
        SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(TransactionIsolationLevel.READ_COMMITTED);
        try {
            session.insert("insertUser", user);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            throw e;
        } finally {
            session.close();
        }
    }

    public void updateUser(User user) {
        SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(TransactionIsolationLevel.READ_COMMITTED);
        try {
            session.update("updateUser", user);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            throw e;
        } finally {
            session.close();
        }
    }

    public void deleteUser(int userId) {
        SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(TransactionIsolationLevel.READ_COMMITTED);
        try {
            session.delete("deleteUser", userId);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            throw e;
        } finally {
            session.close();
        }
    }
}

在上述代码中,我们通过注解@Transactional来表示该类中的方法都需要进行事务管理。接着,我们在每个方法中使用TransactionalSqlSessionDecorator类来获取SqlSession对象,并且设置了事务的隔离级别为READ_COMMITTED。之后,我们在try-catch-finally代码块中实现了事务的提交和回滚操作。

注意,在MyBatis中,我们可以使用多种方式来管理事务,例如通过Spring框架提供的@Transactional注解来实现事务的声明式管理,也可以通过使用SqlSessionTemplate类的事务控制来实现编程式管理。在这个例子中,我们采用了编程式管理事务的方式。

总结

MyBatis 并没有过多地依赖于设计模式,而是根据具体的需求和场景灵活地运用不同的设计模式来解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值