mybatis之SqlSessionFactory、SqlSession

SqlSessionFactory

一个SqlSessionFactory只能连接一个数据库实例,如果需要连接多个数据库,需要构建多个SqlSessionFactory对象

从xml中构建

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>
    <!-- 引入外部properties文件 -->
    <properties resource="jdbc.properties" />
    <!-- 定义类型别名,在xxxMapper.xml文件中就可以用别名代替很长的类名 -->
    <typeAliases>
        <typeAlias type="com.john.spring.bean.Student" alias="Student" />
    </typeAliases>

    <!-- 配置不同环境的参数 -->
    <environments default="development">
        <!-- 开发环境数据库、事务配置 -->
        <environment id="development">
            <!-- 事务管理使用JDBC的事务 -->
            <transactionManager type="JDBC"/>
            <!-- 配置开发环境数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver.className}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 将mapper SQL映射文件包含进来 -->
    <mappers>
        <mapper resource="mappers/StudentMapper.xml"/>
    </mappers>
</configuration>

引入外部配置< properties >

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。其中的属性就可以在整个配置文件中被用来替换需要动态配置的属性值。比如:

<properties resource="jdbc.properties" />
<dataSource type="POOLED">
  <property name="driver" value="${jdbc.driver}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.user}"/>
  <property name="password" value="${jdbc.password}"/>
</dataSource>

这个例子中的 username、password、driver 和 url 属性将会由 properties 元素中设置的相应值来替换。这样就为配置提供了诸多灵活选择。

配置参数< settings >

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

settings支持的属性

设置名描述有效值默认值
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’ 的日志等级必须设置为 WARN) FAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定驱动等待数据库响应的秒数。任意正整数未设置 (null)
defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
safeRowBoundsEnabled允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
safeResultHandlerEnabled允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
mapUnderscoreToCamelCase是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。true | falseFalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 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)类型别名或者全类名.未设置

完整的 settings 元素的示例

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

类型别名< typeAliases >

类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

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

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

一些为常见的 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

多环境配置

Mybatis支持多环境对应不同的配置,例如:开发、测试和生产环境需要有不同的配置

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

根据特定的环境配置构建SqlSessionFactory对象

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);

多环境配置示例

<!-- 多环境配置根节点,并设置默认启用的环境 -->
<environments default="development">
  <!-- 定义development环境参数 -->
  <environment id="development">
     <!-- 指定事务配置 -->
     <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <!-- 配置数据源 -->
    <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>

注意这里的关键点:

  • 默认使用的环境 ID(比如:default=“development”)。
  • 每个 environment 元素定义的环境 ID(比如:id=“development”)。
  • 事务管理器的配置(比如:type=“JDBC”)。
  • 数据源的配置(比如:type=“POOLED”)。

默认的环境和环境 ID 是自解释的,因此一目了然。 你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。

事务管理器 < transactionManager >

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

  • JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
  • MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
    <transactionManager type="MANAGED">
       <property name="closeConnection" value="false"/>
    </transactionManager>
    

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

数据源

  1. UNPOOLED
  2. POOLED
  3. JNDI
  4. 通过Spring提供数据源

SqlSessionFactory示例

单环境配置示例

xml配置方式

jdbc.properties数据源

jdbc.url=jdbc:mysql://localhost:3306/yanfa5
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
jdbc.characterEncoding=utf8

StudentMapper.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">

<!-- namespace对应空Dao接口的全名 -->
<mapper namespace="com.lanou3g.mybatis.dao.StudentDao">
    <!-- 此处的id是查询语句的名称,对应接口中的方法名 -->
    <select id="queryAll" resultType="Student">
        select * from student;
    </select>
</mapper>

mybatis.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>
    <properties resource="jdbc.properties" />
    <typeAliases>
        <typeAlias type="com.lanou3g.mybatis.bean.Student" alias="Student" />
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/StudentMapper.xml" />
    </mappers>
</configuration>

对应数据库表的java类

@Setter
@Getter
public class Student {
    private Integer sid;
    private String sname;
    private Integer sage;
    private String ssex;
    private Integer leaderid;

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", sage=" + sage +
                ", ssex='" + ssex + '\'' +
                ", leaderid=" + leaderid +
                "}\n";
    }
}

dao层接口(操作数据库)

public interface StudentDao {
    List<Student> queryAll();
}

程序运行入口

public class App {
    public static void main(String[] args) throws IOException {
        //1、读入配置文件
        String confPath = "mybatis.xml";
        InputStream is = Resources.getResourceAsStream(confPath);

        //2、构建SqlSessionFactory(用于获取sqlSession)
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3、获取sqlSession对象(用于具体的RUID)
        SqlSession sqlSession = sessionFactory.openSession();

        //4、具体的RUID
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        System.out.println(studentDao.queryAll());
    }
}

注解配置方式

jdbc.properties数据源

jdbc.url=jdbc:mysql://localhost:3306/yanfa5
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
jdbc.characterEncoding=utf8

mybatis.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>
    <properties resource="jdbc.properties" />
    <typeAliases>
        <typeAlias type="com.lanou3g.mybatis.bean.Student" alias="Student" />
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.lanou3g.mybatis.dao.TeacherDao" />
    </mappers>
</configuration>

对应数据库表的java类

@Getter
@Setter
public class Teacher {
    private Integer tid;
    private String tname;
    private Integer cid;

    @Override
    public String toString() {
        return "Teacher{" +
                "tid=" + tid +
                ", tname='" + tname + '\'' +
                ", cid=" + cid +
                "}\n";
    }
}

dao层接口(操作数据库)

public interface TeacherDao {
    //查询语句
    @Select("select * from teacher")
    List<Teacher> queryAll();
}

程序运行入口

public class App {
    public static void main(String[] args) throws IOException {
        //1、读入配置文件
        String confPath = "mybatis.xml";
        InputStream is = Resources.getResourceAsStream(confPath);

        //2、构建SqlSessionFactory(用于获取sqlSession)
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3、获取sqlSession对象(用于具体的RUID)
        SqlSession sqlSession = sessionFactory.openSession();

        //4、具体的RUID
        TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);
        System.out.println(teacherDao.queryAll());
    }
}

多环境配置示例

xml配置和注解配置混用,xml配置操作yanfa5数据库的student表,注解配置操作zzj0301数据库的city表

jdbc.properties 数据源

# yanfa5数据库
jdbc.url=jdbc:mysql://localhost:3306/yanfa5
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
jdbc.characterEncoding=utf8

# zzj0301数据库
city.url=jdbc:mysql://localhost:3306/zzj0301
city.driver=com.mysql.jdbc.Driver
city.user=root
city.password=root
city.characterEncoding=utf8

StudentMapper.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">

<!-- namespace对应空Dao接口的全名 -->
<mapper namespace="com.lanou3g.mybatis.dao.StudentDao">
    <!-- 此处的id是查询语句的名称,对应接口中的方法名 -->
    <select id="queryAll" resultType="Student">
        select * from student;
    </select>
</mapper>

mybatis.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>
    <properties resource="jdbc.properties" />
    <typeAliases>
        <typeAlias type="com.lanou3g.mybatis.bean.Student" alias="Student" />
    </typeAliases>
    <environments default="development">
        <!-- 第一种环境配置 -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
        
        <!-- 第二种环境配置 -->
        <environment id="citydao">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${city.driver}"/>
                <property name="url" value="${city.url}"/>
                <property name="username" value="${city.user}"/>
                <property name="password" value="${city.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/StudentMapper.xml" />
        <mapper class="com.lanou3g.mybatis.environments.dao.CityDao" />
    </mappers>
</configuration>

对应yanfa5数据库student表和对应zzj0301数据库city表的java类

@Setter
@Getter
public class Student {
    private Integer sid;
    private String sname;
    private Integer sage;
    private String ssex;
    private Integer leaderid;

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", sage=" + sage +
                ", ssex='" + ssex + '\'' +
                ", leaderid=" + leaderid +
                "}\n";
    }
}


@Getter
@Setter
public class City {
    private Integer id;
    private String cname;
    private Integer pid;

    @Override
    public String toString() {
        return "City{" +
                "id=" + id +
                ", cname='" + cname + '\'' +
                ", pid=" + pid +
                "}\n";
    }
}

dao层接口(操作数据库)

public interface StudentDao {
    List<Student> queryAll();
}


public interface CityDao {
    //查询语句
    @Select("select * from city")
    List<City> queryAll();
}

程序运行入口

public class App {
    public static void main(String[] args) throws IOException {
        //1、读入配置文件
        String confPath = "mybatis.xml";
        InputStream is1 = Resources.getResourceAsStream(confPath);
        InputStream is2 = Resources.getResourceAsStream(confPath);

        //2、构建SqlSessionFactory(用于获取sqlSession)
        SqlSessionFactory sessionFactory1 = new SqlSessionFactoryBuilder().build(is1,"development");	//括号内的"development"可不写,"development"是配置的默认环境
        SqlSessionFactory sessionFactory2 = new SqlSessionFactoryBuilder().build(is2,"citydao");

        //3、获取sqlSession对象(用于具体的RUID)
        SqlSession sqlSession1 = sessionFactory1.openSession();
        SqlSession sqlSession2 = sessionFactory2.openSession();

        //4、具体的RUID
        StudentDao studentDao = sqlSession1.getMapper(StudentDao.class);
        System.out.println("" + studentDao.queryAll());

        CityDao cityDao = sqlSession2.getMapper(CityDao.class);
        System.out.println("" + cityDao.queryAll());
    }
}

SqlSession

用于真正执行sql语句的对象
操作事务:提交、回滚

void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)

非线程安全的,不能作为一个类的静态变量,最好是用完就在finally块中关掉它


版权声明:本文为ZXY_9264_ANG原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。