Mybatis使用介绍

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

mybatis事务管理

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

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

  • 使用JDBC的事务管理机制。即利用java.sql.Connection对象完成对事务的提交commit()、回滚rollback()和关闭close()等操作。
  • 使用MANAGED的事务管理机制,对于这种机制,Mybatis自身不会去实现事务管理,而是让容器如WebLogic、JBOSS等来实现对事务的管理。

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

  • @Transactional只能被应用到public方法,对于其他非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能。
  • 用spring事务管理器,由spring来负责数据库的打开、提交、回滚。默认遇到运行期例外throw new RuntimeException注释会回滚,即遇到不受检查unchecked的例外回滚,而遇到需要捕获的例外throw new Exception,不会回滚。如果遇到受检查的例外,就是非运行时抛出异常,需要我们指定方式来让事务回滚,要想所有异常都回滚,只需要加上@Transactional(rollbackFor={Exception.class,其他异常})即可。

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

@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,这样在查学生表的时候,就能查询出该学生属于哪个班级了),这样就可以不使用外键了。冗余字段的添加,大概分为以下几种情况:

  • 在处理一对一关系中,可以把冗余字段放在任何一张表中都可以,并且在一对一的时候加的冗余字段,需要设置unique,保证冗余字段的唯一性,因为是一对一的关系,否则就会出现问题的。
  • 在处理一对多或者多对一关系中,需要把冗余字段放在的表中。
  • 在处理多对多关系中,需要使用中间表来维护关系。

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

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

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

参考文章

数据库设计使用外键吗?

mybatis事务配置不起作用

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

欢迎关注国士梅花

国士梅花

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值