重新认识Mybatis系列(一)

重新认识Mybatis

Mybatis是解决数据持久化的框架,采用ORM思想解决实体和数据库映射的问题,对jdbc进行了封装。可以通过简单的xml配置或注解来配置和映射原始类型,接口和pojo类为数据库中的记录。

SqlSessionFactory

每个基于Mybatis的应用都是以一个SqlSessionFactory实例为核心的。

SqlSessionFactory一旦创建就应该在运行期间一直存在,不需要重新创建实例。多次创建SqlSessionFactory被视为一种坏习惯。因此SqlSessionFactory最佳的作用域是应用作用域,所以最简单的就是使用单例模式或静态单例模式创建它。

SqlSessionFactory实例可以通过SqlSessionFactoryBuilder 获得

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 这个类被使用后应该丢弃,它的最佳作用域是方法作用域,可以用它创建多个SqlSessionFactory实例,事后应该释放该类资源

获得SqlSessionFactory的两类方式
  • XML文件构建SqlSessionFactory

Resources配置文件根路径下新建XML文件使用输入流加载配置文件

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

XML文件配置了有关Mybatis的核心设置信息,如数据源,事务管理器,mapper映射文件等

  • 使用Java代码获得SqlSessionFactory
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(YourMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSession

SqlSession是线程不安全的,它不能被共享。因此创建它时的最佳作用域是请求或方法作用域中,不能再类的静态区或实例变量创建它。在Web框架中,将SqlSession放入请求作用域中,确保获取响应后,立即关闭它。

通过SqlSessionFactory实例获取SqlSession实例

try (SqlSession session = sqlSessionFactory.openSession()) {
  YourMapper mapper = session.getMapper(YourMapper.class);
  Blog blog = mapper.selectBlog(100);
}
映射器实例

映射器实例也就是Mapper接口,通过SqlSession实例获得,如上述代码中的YourMapper接口。该实例的最佳作用域是方法作用域,使用完毕即可关闭资源


Mybatis的XML配置文件

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

在这里插入图片描述

属性(properties)

属性可以在配置文件外部配置,也可以在properties下的property标签内配置

<properties resource="config.properties">
  <property name="username" value="root"/>
  <property name="password" value="root"/>
</properties>

在其他地方使用 ${} 便可以使用定义好的属性,如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

其中,username和password会在配置文件下的peopertiy标签内寻找值,driver和url会在外部配置文件config.properties中寻找值。

倘若两处都定义了相同的属性,外部配置文件的属性值会覆盖properties标签内的属性值。

从Mybatis3.4.2开始,可以为属性配置默认值:

<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${username:root1}"/> <!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 'root1' -->
</dataSource>

要启用默认值,则须打开:

<properties resource="config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- 启用默认值特性 -->
</properties>

倘若定义的属性名字中带有,比如user:name,那么在使用默认值的时候会有两个:,这种情况不被允许,必须将默认值的符号:指定为其他符号

<properties resource="config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="!"/> <!-- 修改默认值的分隔符 -->
</properties>
设置(settings)

这些设置将会影响Mybatis运行时的行为,这里列举部分

设置名描述有效值默认值
cacheEnabled全局开启或关闭缓存true|falsetrue
lazyLoadingEnabled全局开启或关闭延迟加载true|falsefalse
useGeneratedKeys允许JDBC自动生成主键true|falsefalse
autoMappingBehavior如何自动映射属性字段,NONE:关闭自动映射;PARTIAL:只映射没有嵌套的字段;FULL:自动映射任何复杂的结果NONE|PARTIAL|FULLPARTIAL
defaultExecutorType配置执行器,SIMPLE:普通;REUSE:重用预处理的执行器;BATCH:不仅重用预处理,还支持批量更新SIMPLE|REUSE|BATCHSIMPLE
mapUnderscoreToCamelCase是否开启驼峰命名自动映射true|falsefalse
localCacheScope默认SESSION:缓存一个会话内的所有查询;STATEMENT:相同的SqlSession内不同查询不会缓存SESSION|STATEMENTSESSION
logImpl指定Mybatis所用的日志实现,未指定自动查找SLF4J|LOG4J|等未设置

一个完整的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类型定义另一个简单的名字,降低冗余的全限定名称

<typeAliases>
  <typeAlias alias="Book" type="com.domain.Book"/>
</typeAliases>

也可以定义一个包,该包下的所有bean用上别名

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

若是该包下bean内定义了注解@Alias,则使用该注解定义的别名

否则将该类名首字母小写作为别名

类型处理器(typeHandlers)

Mybatis从数据库中取出结果,会用到类型处理器将获取到的值转换为Java类型

Mybatis提供许多默认的类型处理器,当然也可以自建类型处理器:例如自建 Java类型的String与JDBC的DATE类型转换处理器

@MappedJdbcTypes(JdbcType.DATE)
public class ExampleTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getString(columnName);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getString(columnIndex);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getString(columnIndex);
    }
}

在XML配置文件中开启类型处理器支持

<typeHandlers>
  <typeHandler handler="com.utils.ExampleTypeHandler"/>
</typeHandlers>

这样当我们从数据库取出DATE类型的结果时,会通过该类型处理器转换为Java的String类型

对象工厂(objectFactory)

Mybatis运行前会解析配置文件,如果配置了自定义的对象工厂,那么创建对象实例时会使用自定义对象工厂,否则使用默认工厂DefaultObjectFactory。当我们想要将对象交给自定义工厂管理,并且自定义属性供对象使用时,便可以创建自定义对象工厂。

public class ExampleObjectFactory extends DefaultObjectFactory {

    @Override
    public Object create(Class type) {
        System.out.println("自定义的对象工厂");
        return super.create(type);
    }

    @Override
    public void setProperties(Properties properties) {
        Iterator iterator = properties.keySet().iterator();
        while (iterator.hasNext()){
            String keyValue = String.valueOf(iterator.next());
            System.out.println(properties.getProperty(keyValue));
        }
        super.setProperties(properties);
    }
    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type);
    }
}

利用Mybatis的对象工厂或继承它自建工厂去管理bean感觉这种事Spring已经可以帮我们做了

环境配置(environments)

Mybatis可以支持连接多个数据库,每一个数据库对应一个SqlSessionFactory

<environments default="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>

至于事务管理器和数据源,连接池等交给Spring去做

映射器(mappers)

配置好数据库环境,接下来要做的事情就是Sql语句了,Mybatis该去哪找Sql语句呢?无论是注解形式还是XML形式,Mybatis都需要知道注解或XML在哪里,那么映射器就是解决这件事情的,由它带Mybatis去找到Sql语句。

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/YourMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.YourMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

以上是Mybatis的XML配置文件,由这些设置可以实现Mybatis不同的运行状态。

下篇记录Mybatis详细的XML映射文件动态SQL

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值