MyBatis_1_配置_映射

MyBatis快速入门

MyBatis是持久层框架,简化了JDBC开发。JDBC存在硬编码与操作繁琐的弊端,而MyBatis几乎免除所有JDBC设置参数与获取结果集的工作。

使用步骤:

  1. Maven创建模块,导入坐标。
  2. 编写mybatis-config.xml核心配置文件。
  3. 创建XxxMapper.java接口文件。
  4. 编写XxxMapper接口对应的SQL映射文件XxxMapper.xml(与接口同名)。
  5. MyBatis配置文件中注册Mapper
  6. Java程序中定义实体类,加载核心配置文件,获取SqlSessionFactory对象
  7. 获取SQLSession对象,执行SQL语句
  8. 处理结果,并释放资源

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>
	<settings>
        <!--在控制台显示SQL语句-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--给实体类取别名, 让实体类使用更简单, 别名使用时不区分大小写-->
    <typeAliases>
        <!--package标签: 给包中的所有类取别名, 默认别名就是类名   name: 包名-->
        <package name="com.lxl.javabean"/>
       <!-- <typeAlias alias="Tag" type="domain.blog.Tag"/>  单个别名-->
    </typeAliases>

    <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/db1?useSSL=false&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--配置接口映射文件/SQL映射文件的位置-->
    <mappers>
        <!--package标签: 扫描包中的所有接口和映射文件 name: 包名
        需要满足两个条件:
            1.接口名和接口映射文件名字要一样
            2.编译后接口和接口映射文件要在同一个包中-->
        <package name="com.lxl.mapper"/>
<!--   <mapper resource="com.lxl.mapper.UserMapper.xml"/> 单个xml引入
	   <mapper class="com.lxl.mapper.UserMapper"/> 单个接口引入
-->
    </mappers>
</configuration>

Java程序代码:

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

//获取SQLSessionFactory对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建一个sqlSession数据库连接会话

//List<User> users = sqlSession.selectList("com.lxl.mapper.UserMapper.selectUsersById",1);
//selectList方法的字符串参数对应mapper标签中的namespace与select标签中的id

// getMapper(XxxMapper.class): 内部会使用动态代理生成接口的实现类 (代理对象)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUsersById(1);

sqlSession.close();//关闭资源

核心配置文件

配置文件结构:

在这里插入图片描述

properties属性

概述:properties作用类似于我们以前使用的properties文件,用来配置系统中固定的参数信息,比如数据库连接地址、用户名、密码等。

properties使用:

<properties  resource="mysql.properties">
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
<!--在 properties 节点中设置了 username、password 这四个参数值,
 然后在 dataSource 节点配置中,用 ${username} 的方式读取到 root 值。-->
<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}"/>
	<!--若mysql.properties有username、password字段,则property中属性将被覆盖-->
		</dataSource>
	</environment>
</environments>

加载优先级:

  1. 首先读取在 properties 元素体内指定的属性。
  2. 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
  3. 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
    SqlSessionFactory factory =
    new SqlSessionFactoryBuilder().build(reader,environment, property);
  4. 因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最次则是 properties 元素中指定的属性。

settings设置

概述:这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

settings使用:

<settings>
<!--指定MyBatis所用日志的具体实现,在控制台显示SQL语句-->
	<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--允许 JDBC 支持自动生成主键,需要数据库驱动支持。默认false。-->
	<setting name="useGeneratedKeys" value="ture"/>
<!--设置超时时间,它决定数据库驱动等待数据库响应的秒数。默认未设置。-->
	<setting name="defaultStatementTimeout" value="1000"/>  
<!--是否开启驼峰命名自动映射,从数据库列名A_COLUMN映射到属性名aColumn。--> 
	<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--全局性地开启或关闭所有映射器配置文件中已配置的任何缓存(二级缓存)--> 
	<setting name="cacheEnabled" value="false"/>
<!--指定全局的自动映射等级:Nome禁用,Partial嵌套以外,Full全部包括嵌套--> 
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>

typeAliases类型别名

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

typeAliases别名使用:

<typeAliases>
	<typeAlias alias="Student" type="com.lxl.bean.Student"/>
	<typeAlias alias="Teacher" type="com.lxl.bean.Teacher"/>
</typeAliases>
<!--Student可在任何XxxMapper.xml中替换com.lxl.bean.Student-->
<!--或者使用包搜索形式,全部指定默认别名,默认为对应类类名-->
<typeAliases>
	<package name="com.lxl.bean"/>
</typeAliases>
<!-- 
在没有注解的情况下,会使用Bean实体类的首字母小写的非限定类名来作为它的别名。 
比如com.lxl.bean.Student的别名为teacher;
若有注解,则别名为其注解值:
@Alias("author")
public class Author {  }
-->

MyBatis内建别名:

  • 基本数据类型别名格式:byte -> _byte,类型名前加下划线
  • 包装类别名格式:Byte -> byte,类名全小写
  • 其他常用类:Object -> object,类名全小写

environment环境配置

概述:

  • MyBatis可以配置成适应多种环境,这种机制有助于将SQL映射应用于多种数据库之中。例如开发、测试和生产环境需要有不同的配置;或者想在具有相同Schema约束的多个生产数据库中使用相同的SQL映射。还有许多类似的使用场景。

  • 尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境。意味着一个数据库对应一个SqlSessionFactory类实例

SqlSessionFactory实例创建:

SqlSessionFactory factory = //指定环境
    new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = //使用默认环境
    new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = //指定环境,并配置属性
    new SqlSessionFactoryBuilder().build(reader, environment, properties);

配置环境:

<environments default="development"><!--default:默认environment的id-->
  <environment id="development">
    <transactionManager type="JDBC">
    <!--事务管理器的配置:-->
    <!--JDBC:直接使用了JDBC的提交和回滚机制,依赖从数据源获得的连接来管理事务。-->
    <!--MANAGED:使用容器来接管事务的整个生命周期-->
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
    <!--数据源的配置(使用的连接池):-->
    <!--POOLED:采用传统的javax.sql.DataSource规范中的连接池-->
    <!--UNPOOLED:采用传统的获取连接的方式,实现标准接口,但无连接池概念。-->    
    <!--JNDI:采用服务器提供的JNDI技术实现,如tomcat服务器使用dbcp连接池-->
    <!--UNPOOLED具体property配置见官网详情页-->
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
  <environment id="test">...</environment>
</environments>

XML映射器

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache – 该命名空间的缓存配置。
  • cache-ref – 引用其它命名空间的缓存配置。
  • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
  • sql – 可被其它语句引用的可重用语句块。
  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。

select标签

select常见属性列表:

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为MyBatis可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType期望从这条语句中返回结果的实体类全限定名或别名。
resultMap对外部resultMap标签的命名引用。
resultSets这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。

SQL语句中的占位符:

  • #{id}:先使用?占位符,执行SQL语句时预处理将?转为具体值。
  • ${id}:直接拼接SQL语句字符串,存在SQL注入安全问题。

insert/update/delete标签

三者常用标签:

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType参照select标签的parameterType属性描述
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让MyBatis分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys(仅适用于insert和update)这会令MyBatis使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键(比如:像MySQL和SQL Server这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅适用于insert和update)指定能够唯一识别对象的属性,MyBatis会使用getGeneratedKeys的返回值或insert语句的selectKey子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn(仅适用于insert和update)设置生成键值在表中的列名,在某些数据库(像PostgreSQL)中,当主键列不是表中的第一列的时候是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

注意:当不支持自动生成主键列的数据库和可能不支持自动生成主键的JDBC驱动,可使用selectkey标签,具体实现查看官方详情页。

sql语句片标签

作用:这个元素可以用来定义可重用的SQL代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的include元素中定义不同的参数值。

sql标签使用:

<sql id="sometable">
${prefix}Table
</sql>

<sql id="someinclude">
from
 <include refid="${include_target}"/>
</sql>

<select id="select" resultType="map">
select
 field1, field2, field3
<include refid="someinclude">
 <property name="prefix" value="Some"/>
 <!--作用在sql标签中,导入的id为sometable的sql标签-->
 <property name="include_target" value="sometable"/>
 <!--导入的sql标签中的include标签,去导入id为sometable的sql标签-->
</include>
<!--最后include标签导入的SQL语句为:from SomeTable-->
</select>
<!--
XML文件中部分特殊字符不允许作为sql语句,需进行处理
1. 转义字符,如 < 写为 &lt;
2. CDATA区,<![CDATA[ 内容 ]]>
-->

resultMap标签

作用:当数据库中表的字段与bean中的实体类属性命名不一致时,可使用结构映射。即resultType属性填写bean中对应实体类后,MyBatis幕后自动生成的ResultMap不能使列名与属性名匹配上时,可以通过自定义resultMap解决。

解决列名与属性名不匹配:

<!--方法一:若列名为a_column,属性名为aColumn的老式命名规则-->
<!--可以在mybatis-config.xml文件中setting设置默认生成resultMap,将查询的列名转为驼峰命名的实体类属性名-->
<settings>
	<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--方法二:查询sql语句中定义列别名,对应实体类的属性名-->
<select id="selectUsers" resultType="User">
select
 user_id		as "id",
 user_name		as "userName",
from some_table
where id = #{id}
</select>
<!--方法三:自定义resultMap映射标签,select中显式引入外部resultMap-->
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<!--主键列的映射标签使用id,该字段被指定为唯一标识,以此提高性能-->
<result property="username" column="user_name"/>
<!--非主键列映射标签使用result-->
</resultMap>

<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name
from some_table
where id = #{id}
</select>

resultMap属性:

属性描述
id当前命名空间中的一个唯一标识,用于标识一个结果映射。
type类的完全限定名, 或者一个类型别名(关于内置的类型别名,可以参考上面的表格)。
autoMapping如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)。
extends该resultMap继承另一个resultMap,一般而言对应实例类的继承关系,结果注入时,确保父元素的映射关系无误。即只需写子类的特有属性,该属性自行获取父类的resultMap来映射父类中属性。

resultMap的子标签:

标签名标签描述
constructor用于在实例化类时,注入结果到构造方法中。
id注入到字段或JavaBean属性的主键结果,标识id可提高性能。
result注入到字段或JavaBean属性的普通结果。
association一个复杂类型的关联,可将许多结果将包装成指定类型
collection一个复杂类型的集合,将结果集包装成对应类型后加入集合
discriminator使用结果值来决定使用那个resultMap
id、result映射标签

作用:这些元素是结果映射的基础。id和result元素都将一个列的值映射到一个简单数据类型(String,int,double,Date等的属性或字段。

属性:

属性描述
property映射到列结果的字段或属性。如果JavaBean有这个名字的属性(property),会先使用该属性。否则MyBatis将会寻找给定名称的字段(field)。 无论是哪一种情形,你都可以使用常见的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。
column数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。
javaType一个Java类的全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个JavaBean,MyBatis通常可以推断类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType 来保证行为与期望的相一致。
constructor构造器标签:

作用:resultMap标签中的id和result标签映射到javabean类都是通过修改对象属性(set)。但某些情况下,实体类没有定义无参构造与set方法(有参构造的不可变类),此时可通过定义constructor标签将查询结果注入到对应bean类有参构造器中并生成对象。(即使MyBatis支持私有属性映射,但有些需求更青睐通过构造器生成bean类实例)。

子标签:

标签名标签描述
idArg被注入到构造方法的一个主键结果,标识id可提高性能。
arg被注入到构造方法的一个普通结果

子标签属性:

属性描述
column数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。同时可认为给select属性嵌套查询提供参数。
javaType一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
select用于加载复杂类型属性的映射语句的 ID,它会从 column 属性中指定的列检索数据,作为参数传递给此 select 语句。后续association标签中举例。
resultMap结果映射的ID,可以将嵌套的结果集映射到一个合适的对象树中。 它可以作为使用额外select语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。这样的ResultSet将会将包含重复或部分数据重复的结果集。为了将结果集正确地映射到嵌套的对象树中,MyBatis 允许你“串联”结果映射,以便解决嵌套结果集的问题。后续association标签中举例。
name构造方法形参的名字。从3.4.3版本开始,通过指定具体的参数名,可以以任意顺序写入arg元素。

使用:

<!--构造器:public User(int in,String username,int age)-->
<resultMap id="userMap" type="user">
<constructor>
 <idArg column="id" javaType="int" name="id" />
 <arg column="age" javaType="_int" name="age" />
 <arg column="username" javaType="String" name="username" />
</constructor>
</resultMap>
association关系标签

作用:

  • 关联(association)元素处理“一对一”类型的关系,如杯子与杯盖的关系,正常来说一个杯子有一个杯盖,同时杯子与杯盖都是javabean类型。
  • 关联的不同之处是,你需要告诉MyBatis如何加载关联。MyBatis有两种不同的方式加载关联:
    • 嵌套Select查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。
    • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。
  • 普通的结果映射相比,它只在 select 和 resultMap 属性上有所不同。

基本使用:

<resultMap id="userMap" type="user">
  <id property="id" column="id"></id>
  <association javaType="UserInfo" property="userinfo" >
    <id property="id" column="id"></id>
    <result property="isMarry" column="is_marry"/>
  </association>
  <!--将查询的结果集中对应列的值注入userinfo实例的属性中-->
</resultMap>

属性:

属性描述
property映射到列结果的字段或属性。如果用来匹配的JavaBean存在给定名字的属性,那么它将会被使用。否则MyBatis将会寻找给定名称的字段。 无论是哪一种情形,你都可以使用通常的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。
javaType一个 Java 类的完全限定名,或一个类型别名。 如果你映射到一个JavaBean,MyBatis通常可以推断类型。然而如果你映射到的是HashMap,那么你应该明确地指定javaType 来保证行为与期望的相一致。
column数据库中的列名,或者是列的别名。注意:在使用复合主键的时候,你可以使用 column=“{prop1=col1,prop2=col2}” 这样的语法来指定多个传递给嵌套Select查询语句的列名。这会使得prop1和prop2作为参数对象,被设置为对应嵌套Select语句的参数。
select用于加载复杂类型属性的映射语句的ID,它会从column属性指定的列中检索数据,作为参数传递给目标select语句。
fetchType懒加载(使用该嵌套查询的结果时才加载),有效值为lazy和eager。 指定属性后,将在映射中忽略全局配置参数lazyLoadingEnabled,使用属性的值。
resultMap结果映射的ID,详情参照constructor标签中的解释。
columnPrefix指定columnPrefix列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中,如子标签中的column="id"且父标签中的columnPrefix=“stu”,那么实际上读取的列名为stu_id。
autoMapping如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性autoMappingBehavior。注意,本属性对外部的结果映射无效,所以不能搭配select或resultMap元素使用。默认值:未设置(unset)。

嵌套select属性

使用案例:

<resultMap id="selectUserById" type="user">
<association property="userinfo" column="id" 			javaType="UserInfo" select="selectUserInfoById"/>
<!--获取第一次查询到的id,作为嵌套查询的条件参数-->
</resultMap>

<select id="selectUserInfoById" resultMap="userinfo">
SELECT * FROM userinfo WHERE user.id = #{id};
</select>

嵌套select查询弊端:

这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:

  • 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
  • 对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。

嵌套select查询的结果映射:

<resultMap id="selectUserById" type="user">
  <id property="id" column="id" ></id>
  <association property="userinfo" column="id"
               javaType="UserInfo" select="selectUserInfoById"
               resultMap="userInfoMap"/>
  <!--将嵌套查询的结果依照映射userInfoMap,注入UserInfo实例中-->
</resultMap>

<resultMap id="userInfoMap" type="UserInfo">
    <id property="id" column="id"></id>
    <result property="isMarry" column="is_marry"/>
</resultMap>
discriminatior选择标签

作用:当实体类中的某个属性可能对应多种其类型的子类型结果,查询的时候需要甄别是需要用到那种子类型的resultMap进行数据映射。只要查询返回了不同的结果,就用discriminator。

注意:

  • 当该鉴别器匹配到一个结果后,其余case就会被忽略。类似于java中的switch-case。
  • 若匹配不到任何一个case,mysql只会使用鉴别器外的映射关系。

使用:

<resultMap id="userMap" type="user">
  <id property="id" column="id" />
  <result property="name" column="username"/>
  <discriminator javaType="int" column="sex_type">
    <!--根据性别类型,进行不同的sex属性映射-->
    <case value="0" resultMap="girlResultMap"/>
    <case value="1" resultMap="boyResultMap"/>
  </discriminator>
</resultMap>

cache缓存标签

概述:现在我们每次执行相同的SQL语句都是去数据库中查询,存在效率问题。MyBatis框架提供了缓存策略,通过缓存策略可以减少查询数据库的次数,提升系统性能。在MyBatis框架中缓存分为一级缓存和二级缓存。一般来说缓存在内存中。

一级缓存:

  • sqlSession范围的缓存,只能在同一个sqlSession内部有效。它本身已经存在,一级缓存不需要手动处理,可以直接使用。
  • 可以通过MyBatis配置文件的setting中设置缓存
  • SqlSession的clearCache方法可清理一级缓存。
  • 当调用SqlSession的修改、添加、删除、提交、关闭等方法时,一级缓存会被清空。

二级缓存:

  • 二级缓存是mapper映射级别缓存,作用范围跨越SqlSession,即可以在多个SqlSession之间共享二级缓存数据。

开启二级缓存:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <!--mybatis-config.xml配置开启二级缓存-->
</settings>

<mapper namespace="com.lxl.bean.UserMapper">
  <cache/>
  <!--cache标签表示该mapper文件查询结果将会放入二级缓存-->
</mapper>
public class User implements Serializable{ ... }
//对应查询的实体类实现Serializable接口

//若不在UserMapper.xml文件中添加cache标签
//还可以通过注解的形式开启mapper二级缓存
@CacheNameSpace(blocking = true)
public interface UserMapper{ ... }

public void test04() {
    // 第一个sqlSession
    SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
    //工具类MyBatisUtils获取sql会话
    UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
    User user1 = mapper1.findUserById(1);
    System.out.println("第一次" + user1.getUsername());
    sqlSession1.close(); // 要关闭会话,数据才会保存二级缓存中

    // 第二个sqlSession
    SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = mapper2.findUserById(1);
    System.out.println("第二次" + user2.getUsername());
    sqlSession2.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值