Mybatis使用介绍

2017-09-04  本文已影响233人  国士无双A

最近项目比较忙,现在终于抽出空来,分享下自己在学习mybatis orm框架时遇到的一些问题,希望对你有所帮助。

mybatis事务管理

事务:是一步或几步操作组成的逻辑执行单元,这些基本操作作为一个整体执行单元,它们要么全部执行,要么全部取消执行,绝不能仅仅执行一部分。事务具备4个特性:原子性、一致性、隔离性(并发执行的事务之间不能相互影响)、持续性(持续性也被称为持久性,指事务一旦提交,对数据所做的任何改变都要记录到永久存储器中,通常就是保存到物理数据库)。

mybatis的事务管理分为两种形式:

一般我们在进行DML操作(delete、insert、update)的时候,都需要进行事务管理的,操作不成功的话,就需要进行事务回滚。在具体的项目中,一般使用@Transactional注解来管理事务,具体使用如下:

简单来说运行时异常回滚,做如下配置即可:

@Transaction(rollbackFor=RuntimeException.Class)

所有异常都回滚,做如下配置即可:

@Transaction(rollbackFor=Exception.Class)

如果项目中使用的是Spring+Mybatis,则没有必要配置事务管理器,因为Spring模块会使用自带的管理器来覆盖前面的配置。下面说下自己在Spring整合Mybatis时遇到的一个问题,就是mybatis事务配置不起作用,先复原下当时的配置如下所示:

springmvc-config.xml里面有段这样的配置:

<!-- 指定包的扫描位置 -->
<context:component-scan base-package="com.dodonew"/>

applicationContext-datasource.xml里面有段这样的配置:

<!-- 扫描com.dodonew包下面的java文件,有Spring的相关注解的类,则把这些类注册为Spring的bean。 -->
<context:component-scan base-package="com.dodonew"/>

<!-- JDBC事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

这样的配置是有问题的,当数据插入失败的时候,并没有对数据进行回滚,这是为什么呢?这是因为在springmvc-config.xml文件中指定扫描位置的时候,也扫描了带有@Service注解的类,所以造成事务回滚失败。因为springmvc-config.xml与applicationContext-datasource.xml不是同时加载,如果不进行这样的设置,那么spring就会将所有带@Service注解的类都扫描到容器中,等到加载applicationContext-datasource.xml的时候,会因为容器已经存在Service类,使得cglib将不再对Service进行代理,直接导致的结果是applicationContext-datasource.xml中的事务配置不起作用,发生异常时,无法对数据进行回滚。所以,springmvc-config.xml中的配置应该更改为如下所示:

<!-- 扫描com.dodonew包下面的java文件,有Spring的相关注解的类,则把这些类注册为Spring的bean。 -->
<context:component-scan base-package="com.dodonew.controller"/>

也就是说指定扫描的位置不要包括@Service就可以了。

mybatis缓存

Mybatis的查询缓存分为一级缓存和二级缓存,一级缓存是SqlSession级别的缓存,二级缓存是mapper级别的缓存,二级缓存是多个SqlSession共享的。Mybatis通过缓存机制减轻数据压力,提高数据库性能。

一级缓存(SqlSession级别)

�在操作数据库时需要构建SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间的缓存数据区域(HashMap)是互相不影响的。

二级缓存(mapper级别)

二级缓存是mapper级别的缓存,使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMap进行数据存储。相比一级缓存,二级缓存的范围更大,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。SqlSession(一级缓存)和Mapper(二级缓存)需要注意的点:

  1. 只要进行了DML操作(insert、update、delete),不管有没有把操作提交到数据库,mybatis都会把SqlSession(一级缓存)和Mapper(二级缓存)给清除掉的。
  2. 当进行了commit操作或close操作,mybatis会把SqlSession(一级缓存)给清除掉,二级缓存是不会清除掉的。
  3. mybatis首先去一级缓存查找,如果一级缓存查找不到的话,就会到二级缓存去查找,二级缓存还查找不到的话,就到数据库去查找。

数据库中表的外键

在实际的项目开发当中,在建表的时候,不要添加外键,这样每个表都是相对独立的。在业务需求中,有需要进行关联的,在代码层面完成关联,避免在表中进行关联,这样在整个数据库当中表的关联关系是比较清晰的。使用外键比较多的话,会有性能问题:

所以在互联网行业应用不推荐使用外键,因为用户量大、并发度高,因此数据库服务器很容易成为性能瓶颈,尤其受IO能力限制,且不能轻易地水平扩展。在数据库需要使用外键的地方,可以通过添加冗余字段来解决。比如班级表(Clazz)和学生表(Student),班级表列名为id、code,学生表列名为id、name、age、sex、clazz_id(这个是冗余字段,是Clazz表的主键id,这样在查学生表的时候,就能查询出该学生属于哪个班级了),这样就可以不使用外键了。冗余字段的添加,大概分为以下几种情况:

另外,在使用mybatis的时候,经常会做如下配置:

<setting name="useGeneratedKeys" value="false"/>

这个配置的主要作用就是,不允许使用mybatis自定义的主键(比如由程序生成的UUID 32位编码作为键值,比如指定UserId为主键),因为这样数据库本身的PK生成策略会被覆盖掉,一般情况下,我们会使用数据库本身自带的PK生成策略。但是需要注意的一点是,mysql数据库支持自动生成主键的,Oracle则不支持自动生成主键的。

参考文章

数据库设计使用外键吗?

mybatis事务配置不起作用

mybatis事务配置以及事务的传播性与隔离级别详解

欢迎关注国士梅花

国士梅花
上一篇下一篇

猜你喜欢

热点阅读