关于数据库:ORM的事务实现

31次阅读

共计 3376 个字符,预计需要花费 9 分钟才能阅读完成。

一、JDBC
晚期 SUN 公司想编写一套能够连贯天下所有数据库的 API,然而当他们刚刚开始时就发现这是不可实现的工作,因为各个厂商的数据库服务器差别太大了。起初 SUN 开始与数据库厂商们探讨,最终得出的论断是,由 SUN 提供一套拜访数据库的标准(就是一组接口),并提供连贯数据库的协定规范,而后各个数据库厂商会遵循 SUN 的标准提供一套拜访本人公司的数据库服务器的 API 呈现。SUN 提供的标准命名为 JDBC,而各个厂商提供的,遵循了 JDBC 标准的,能够拜访本人数据库的 API 被称之为驱动。
数据库连接池:

C3P0

DBCP– Apache CommonPool

Druid

Hikari

二、ORM
Hibernate

Hibernate 是一个开源的对象关系映射框架,它对
JDBC 进行了十分轻量级的对象封装,它将 POJO 与
数据库表建设映射关系,是一个全自动的 orm 框架
,hibernate 能够主动生成 SQL 语句,主动执行,
使得 Java 程序员能够应用面向对象的思维来操纵数
据库。
Hibernate 里须要定义实体类和 hbm 映射关系文件
(IDE 个别有工具生成)。
Hibernate 里能够应用 HQL、Criteria、Native SQL
三种形式操作数据库。
也能够作为 JPA 适配实现,应用 JPA 接口操作。

Mybatis

MyBatis 是一款优良的长久层框架,它反对定制化 SQL、存储过程以及高级映射。MyBatis 防止了简直所有的 JDBC 代码和手动设置参数以及获取后果集。Mybatis 能够应用简略的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects, 一般的 Java 对象)映射成数据库中的记录

Mybatis 与 Hibernate 的区别?

Hibernate 是全自动,Mybatis 是半自动。

Mybatis

长处:原生 SQL(XML 语法),直观,容易优化
毛病:繁琐,能够用 Mybatis-generator、Mybatis-Plus 之类的插件补救
Hibernate

长处:简略场景不必写 SQL(HQL、Cretiria、SQL)
毛病:不好优化 sql,对 DBA 不敌对
Spring 治理事务

咱们先看看 JDBC 如何操作事务?

public void updatePrice() throws SQLException {

    try {Connection conn = getConnection();
        // 敞开主动提交
        conn.setAutoCommit(false);
        String sql = "update goods set price =? where id=?";
        PreparedStatement ptmt = conn.prepareStatement(sql); 
        ptmt.setDouble(1, 3500);
        ptmt.setString(2, "1");
        // 执行
        ptmt.execute();
        // 提交事务
        conn.commit();} catch (Exception e) {
        // 回滚事务
       conn.rollback();
       e.printStackTrace();}
}

实现原理:事务管理器 +AOP

源码剖析 Spring 事务实现过程

示例代码:
我在 goodsService.updatePrice 办法上加了事务注解。

@RequestMapping(“/updateprice”)

public String updateprice(Double price,Integer age){goodsService.updatePrice(1,price);
    int i=10/0;
    userService.updateAge(1,age);
    return "sucess";
}


七种事务的流传行为:

PROPAGATION_REQUIRED (默认) 示意以后办法必须在一个具备事务的上下文中运行, 如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话从新开启一个事务。

PROPAGATION_SUPPORTS 示意以后办法不必须在一个具备事务的上下文中运行, 如:ServiceA.methodA()调用 ServiceB.methodB(), 如果 methodA 办法上有事务, 那么 methodB 退出他的事务, 如果 methodA 上没有事务, 那么 methodB 也不开事务

PROPAGATION_MANDATORY 必须被开启事务的办法调用, 否则报错

PROPAGATION_REQUIRES_NEW 强制本人开启一个新的事务, 如果一个事务曾经存在, 那么将这个事务挂起. 如 ServiceA.methodA()调用 ServiceB.methodB(),methodB()上的流传级别是 PROPAGATION_REQUIRES_NEW 的话, 那么如果 methodA 报错, 不影响 methodB 的事务, 如果 methodB 报错, 那么 methodA 是能够抉择是回滚或者提交的, 就看你是否将 methodB 报的谬误抛出还是 try catch 了.

PROPAGATION_NOT_SUPPORTED 总是非事务的执行, 并且挂起任何事务. 就是如果 methodA 办法执行到 methodB 这里了,methodA 的事务就被挂起, 而后 methodB 非事务的执行, 而后等 methodB 办法运行完结,methodA 的事务再持续. 这个的益处就是 methodB 报错了不会让 methodA 回滚.

PROPAGATION_NEVER 总是非事务地执行,如果存在一个流动事务,则抛出异样

PROPAGATION_NESTED 示意如果以后办法正有一个事务在运行中, 则该办法应该运行在一个嵌套事务中 , 被嵌
套的事务能够独立于被封装的事务中进行提交或者回滚。如果封装事务存在, 并且外层事务抛出异样回滚,那么内层事务必须回滚, 反之, 内层事务并不影响外层事务。如果封装事务不存在, 则同 propagation. required 的一样

事务生效的几个起因:

spring 的事务注解 @Transactional 只能放在 public 润饰的办法上才起作用,如果放在其余非 public(private,protected)办法上,尽管不报错,然而事务不起作用
如果采纳 spring+springmvc,则 context:component-scan 反复扫描问题可能会引起事务失败。如果 spring 和 mvc 的配置文件中都扫描了 service 层,那么事务就会生效。
起因:因为依照 spring 配置文件的加载程序来讲,先加载 springmvc 配置文件,再加载 spring 配置文件,咱们的事物个别都在 srping 配置文件中进行配置,如果此时在加载 srpingMVC 配置文件的时候,把 servlce 也给注册了,然而此时事物还没加载,也就导致前面的事物无奈胜利注入到 service 中。所以把对 service 的扫描放在 spring 配置文件中或是其余配置文件中。
如应用 mysql 且引擎是 MyISAM,则事务会不起作用,起因是 MyISAM 不反对事务,能够改成 InnoDB 引擎
@Transactional 注解开启配置,必须放到 listener 里加载,如果放到 DispatcherServlet 的配置里,事务也是不起作用的。
Spring 团队倡议在具体的类(或类的办法)上应用 @Transactional 注解,而不要应用在类所要实现的任何接口上。在接口上应用 @Transactional 注解,只能当你设置了基于接口的代理时它才失效。因为注解是 不能继承 的,这就意味着如果正在应用基于类的代理时,那么事务的设置将不能被基于类的代理所辨认,而且对象也将不会被事务代理所包装。
在业务代码中如果抛出 RuntimeException 异样,事务回滚;然而抛出 Exception,事务不回滚;默认对 RuntimeException 回滚
如果在加有事务的办法内,应用了 try…catch.. 语句块对异样进行了捕捉,而 catch 语句块没有 throw new RuntimeExecption 异样,事务也不会回滚
在类 A 外面有办法 a 和办法 b,而后办法 b 下面用 @Transactional 加了办法级别的事务,在办法 a 外面 调用了办法 b,办法 b 外面的事务不会失效。起因是在同一个类之中,办法相互调用,切面有效,而不仅仅是事务。这里事务之所以有效,是因为 spring 的事务是通过 aop 实现的。

正文完
 0