【Mybatis一】Mybatis使用、配置、CRUD、配置、设置、映射器

Mybatis

1.简介

image-20220323105211139

1.1什么是 MyBatis?

  • MyBatis 是一款优秀的 持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis。2013年11月迁移到Github

如何获得mybatis

  • maven

    • <dependencies>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.2</version>
          </dependency>
      </dependencies>
      
  • GitHub:

  • 中文文档:MyBatis中文网

1.2 持久化

数据持久化

  • 数据库(jdbc), io 文件持久化
  • 对象放内存中, 断电即逝

为什么需要持久化

  • 有一些对象, 不能丢掉

1.3 持久层

Dao层, Service层, Controller层…

  • 完成持久化工作的代码块
  • 层界限十分明显

1.4 为什么需要Mybatis?

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

  • 方便

  • 传统的讲标代码太复杂了, 做简化. 框架, 自动化

  • 优点

    • **简单易学:**本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
    • **灵活:**mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
    • **解除sql与程序代码的耦合:**通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
    • 提供映射标签,支持对象与数据库的orm字段关系映射。
    • 提供对象关系映射标签,支持对象关系组建维护。
    • 提供xml标签,支持编写动态sql。

2.第一个Mybatis程序

思路: 环境搭建, 导入mybatis, 编写代码, 测试

2.1 搭建环境

1,创建maven项目, 导入依赖

<!--导入依赖-->
<dependencies>
    <!--mysqlq驱动-->
    <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>
        <scope>test</scope>
    </dependency>
</dependencies>

2,建立子工程, 在resources下建mybatis配置文件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="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

3, 建立MybatisUtils工具类, 获取SQLSession对象

package com.ccc.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;

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {

        try {
            //获取SqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    //SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2.3 编写代码

  • 实体类

    • public class User {
          private int id;
          private String name;
          private String pwd;
          //添加getset
      
  • Dao接口

    public interface UserMapper {
        public List<User> getUserList();
    }
    
  • 接口实现类变成了mapper配置文件UserMapper.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/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <mappers><!--每个mapper都需要注册-->
            <mapper resource="com/ccc/dao/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  • 需在pom.xml加入导出包设置, 不加resources里的mybatis-config.xml不能导出, 会报错

<!--build配置导出方案, 解决资源导出失败的问题-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

2.4 测试

public class UserDaoTest {
    @Test
    public void  test(){
        //第一步, 获的sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        for (User user : mapper.getUserList()) {
            System.out.println(user.getName());
        }
        //关闭sqlsession
        sqlSession.close();
    }
}

image-20220323150717439

成功打印

2.5, 报错注意点

UserMapper.xml

image-20220323151726360

mybatis-config.xml

  1. 需要注册mapper
  2. 如果报ssl错误把useSSL=false , mysql8还要加时区

image-20220323152422283

确保target里导出了mybatis-config.xml

image-20220323151853320

如果没有, 右边的build配置导出方案到pom.xml中, 在clear, maven项目重新运行

image-20220323152038388

3.CRUD

3.1. NameSpace

namespace中的包名要和Dao/mapper接口的包名一致

3.2. 增删改查

<mapper namespace="com.ccc.dao.UserMapper">
    <select id="getUserList" resultType="com.ccc.pojo.User" parameterType="">
        select * from mybatis.user
    </select>
</mapper>
  • id 就是对应的namespace中的方法名
  • resultType: SQL语句的返回值
  • parameterType,: 参数类型

mapper

public interface UserMapper {
    List<User> getUserList();
    User getUserByID(int id);
    int addUser(User user);
    int updateUser(User user);
    int deleteUser(int id);
}

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.ccc.dao.UserMapper">
    <select id="getUserList" resultType="com.ccc.pojo.User">
        select * from mybatis.user
    </select>
    <select id="getUserByID" resultType="com.ccc.pojo.User" parameterType="int">
        select * from mybatis.user where id = #{id}
    </select>
    <insert id="addUser" parameterType="com.ccc.pojo.User" >
        insert into mybatis.user (id,name,pwd) value (#{id},#{name},#{pwd})
    </insert>
    <update id="updateUser" parameterType="com.ccc.pojo.User"  >
        update mybatis.user set name = #{name} , pwd = #{pwd} where id = ${id}
</update>
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id = #{id}
    </delete>
</mapper>

测试

package com.ccc.dao;

import com.ccc.pojo.User;
import com.ccc.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class UserDaoTest {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        for (User user : mapper.getUserList()) {
            System.out.println(user);
        }
    }
    @Test
    public void getUserByID(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByID(1);
        System.out.println(user);
        sqlSession.close();
    }
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.addUser(new User(4, "麻子", "123123"));
        if (1 > 0) {
            //提交事物
            sqlSession.commit();
            System.out.println("插入成功");
        }
        System.out.println(i);
        sqlSession.close();
    }

    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.updateUser(new User(4, "李四1", "321"));
        if (i > 0) {
            sqlSession.commit();
            System.out.println("修改成功");
        }
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int i = mapper.deleteUser(4);
        if (i > 0) {
            sqlSession.commit();
            System.out.println("修改成功");
        }
        sqlSession.close();
    }
}

总结

  • 增删改需要提交事物sqlSession.commit();才能操作成功
  • 一个结构对应一个mapper

3.3.万能的Map(传递参数)

假设,实例类, 或数据库中的表, 字段或者参数过多, 可以考虑使用map

public interface UserMapper {
    int updateUser1(Map<String,Object> map);
}
<update id="updateUser1" parameterType="map">
    update mybatis.user set name = #{name} , pwd = #{pwd} where id = ${id}
</update>

@Test
public void updateUser1(){
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<>();
    map.put("id",3);
    map.put("name","张三3");
    map.put("pwd","123456");
    int i = mapper.updateUser1(map);
    if (i > 0) {
        sqlSession.commit();
        System.out.println("修改成功");
    }
    sqlSession.close();
}

image-20220323210222431

3.4.模糊查询

1,传递参数时传入%%, 这种情况可能会出现SQL注入

image-20220323211459788

2, 写SQL的时候定死,传递的时候只能是一个值

image-20220323211709412

4, 配置解析

4.1核心配置文件

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

4.2.环境配置(environments)

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

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

可以通过default来切换配置

image-20220323213025652

事务管理器 默认JDBC , 连接池 POOLED’

事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:

    <transactionManager type="MANAGED">
      <property name="closeConnection" value="false"/>
    </transactionManager>
    

提示 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

数据源(dataSource)

POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

4.3.属性(properties)

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

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

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.0.201/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8
username=root
password=123456

image-20220323213540655

(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".

<configuration>
    <!--引入外部配置文件-->
    <properties resource="db.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>
        <mapper resource="com/ccc/dao/UserMapper.xml"/>
    </mappers>
</configuration>

第二种

<!--引入外部配置文件-->
<properties resource="db.properties">
    <property name="password" value="123123"/>
</properties>
  • 如果外面的db.properties也有password属性, 优先使用外部的

4.4.类型别名(typeAliases)

  • 类型别名可为 Java 类型设置一个缩写名字。
  • 它仅用于 XML 配置,意在降低冗余的全限定类名书写

第一种

<!--类型别名-->
<typeAliases>
    <typeAlias type="com.ccc.pojo.User" alias="user"/>
</typeAliases>

第二种

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

<!--类型别名-->
<typeAliases>
    <package name="com.ccc.pojo" />
</typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:

@Alias("user")
public class user {
    ...
}
  • 默认是按照实力类的类名小写
  • 可以在实体类上增加注解Alias起别名

数据类型别名

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

4.5.设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

image-20220323215529625

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置)未设置 (null)
safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION | STATEMENTSESSION
jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | falsefalse
logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置

4.6.其他配置

4.7.映射器(mappers)

MapperRegistry: 注册绑定外面的Mapper文件

方式一, 推荐使用

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

方式二, 使用class

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="com.ccc.dao.UserMapper"/>
</mappers>

注意点:

  • 接口和他的mapper.xml需要在同一个包下面
  • 接口需要是mapper结尾

方式三 使用扫描包

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

注意点:

  • 接口和他的mapper.xml需要在同一个包下面
  • 接口需要是mapper结尾

4.8.作用域(Scope)和生命周期

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

image-20220323221228129

SqlSessionFactoryBuilder
  • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
  • 局部变量
SqlSessionFactory
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。

  • 可以想象成一个数据库连接池

  • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。

  • 因此 SqlSessionFactory 的最佳作用域是应用作用域。

  • 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession
  • 每个线程都应该有它自己的 SqlSession 实例。
  • SqlSession 的实例不是线程安全的,因此是不能被共享的
  • 所以它的最佳的作用域是请求或方法作用域
  • 用完之后赶紧关闭, 否则资源被占用
  • 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值