栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

框架技术 ---- Spring收尾

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

框架技术 ---- Spring收尾

Spring

内容管理

Spring事务

Spring事务管理事务实例模拟给业务方法增加事务

注解@Transactional使用AspectJ的aop配置管理事务 Spring web

Javaweb —Spring


Spring收尾—事务、web


Spring集成mybatis最关键的就是3个对象,Datasource对象、SqlSessionFactory对象、利用MapperScannerConfig创建的dao对象 — 都是在配置文件中完成,德鲁伊druid不需要driver的信息

Spring事务
    事务是什么?

事务其实就是完成业务逻辑的一组sql语句的集合【一般是DML】,集合中有多条sql语句,包括UPDATe、INSERT、DELETE等,事务的特点就是ACID, atomic(原子性)、consistency(一致性) 同时成功或者同时失败、isolation(隔离性)、durability(持久性),作为一个整体执行。

    什么时候使用事务?

当操作涉及多个表,或者而多个DML语句,这些语句对修改表中的数据,为了确保数据安全,需要使用事务,确保同时成功完成功能,或者同时失败保证安全【转账,不能增加或者减少了】

    在程序中,事务应该在什么位置处理?

事务本来在Dao层,但一般情况下,需要将事务上升到业务层,这样做是为了使用事务的特性来管理具体的事物。因为service层一般会调用多个dao方法,执行多个sql语句,这个时候,为了确保数据的安全,就必须要使用事务

    在JDBC或者Mybatis如何使用事务?

在控制台单独写事务,开启事务,rollback或者commit;并且还有是事务的4个隔离级别,mysql默认repeatable;JDBC访问数据库,使用的是Connection对象来执行的事务,最开始setAutoCommit为false;然后最后commit;在catch中rollback; 而在mybatis中使用的是sqlSession对象来处理的事务,比如rollback; 之前的整合过程是因为是自动提交事务,所以没有凸显事务

不同的数据库访问技术,处理事务的对象、方法是不同的,比如JDBC和Mybatis的方法,并且访问数据库访问技术使用的事务的原理,掌握多种数据库中处理逻辑,什么时候提交事务、回滚事务,处理方法。

多种数据库的访问技术,有不同的机制处理的机制和对象,Spring提供了处理事务的统一模型【将事务处理规范化】,使用统一的步骤,完成多种不同数据库访问技术的事务处理、比如mybatis、hibernate等访问数据库的技术 ------> spring事务处理模型: 定义了事务处理的各个方面,定义了最基本的处理步骤【规范化】就像AOP一样声明式事务:把事务相关的资源和内容都提供给spring、spring就能处理事务的提交回滚了,几乎不需要写代码

在Spring框架中,有两种实现事物的方式:

    使用Spring的事务注解管理事务使用AspectJ的AOP配置管理事务
Spring事务管理

Spring事务管理,主要依赖的两个重要的接口

PaltformTransactionManager

上面已经提到了只要将事务的资源交给spring就可以了,那么事务的提交、回滚是依靠的就是事务管理器对象,代替完成rollback和commit; 事务管理器是一个接口和众多实现类:也就是PaltformTransactionManager接口和其实现类:Spring把每一种数据库访问技术对应的事务处理类都创建了的

如果使用的mybatis访问数据库------>spring创建好的是DataSourceTransactionManager

如果使用的是hibernate访问数据库---->spring船舰号的是HibernateTransactionManager ……

虽然不需要自己创建类,但是需要告诉Spring使用的是哪一种技术,这里只需要在配置文件中使用bean标签声明事务管理器实现类,如果使用mybatis,那么


TransactionDefinition

除了告诉spring使用什么,还需要告诉事务的类型。TransactionDefinition接口中定义了事务描述相关的常量:其中包括事务的隔离级别、传播行为、默认的延时时限、操作等,说明的事务的信息包括

事务的隔离级别 : spring框架使用的是几个整数常量表示的,ISOLATION开头,mysql默认是REPEATABLE_READ;oracle为READ_COMMITED

ISOLATION_READ_UNCOMMITED: 读未提交,未解决任何的并发问题ISOLATION_READ_COMMITED: 读已提交,存在不可重复度和幻读ISOLATION_REAPTABLE_READ: 可重复读、解决脏读,不可重复度,但是存在幻读ISOLATION_SERLAIZABLE: 串行化,不存在并发的问题

事务的超时时限: 表示一个方法的最长的执行时间。如果方法执行时间超过了时间,事务就会回滚,单位是秒,一般不设置,使用默认的TIMOUT_DEFAULT: -1

事务的传播行为: 控制业务方法是不是有事务的,是什么样的事务(7个)处于不同事务中的方法在相互调用的时候【方法栈】,执行期间业务的维护情况。比如A事务的方法doSome调用B事务的方法doOther(),调用执行期间的事务的维护情况,称为事务的传播行为,事务的传播行为加在方法上 。 传播行为都是以PROPAGATION开头的

PROPAGATION_REQUIRED: required,指定的方法必须在事务内执行,当前方法存在事务,必须加入当前的事务,没有则创建新事务。是Spring的默认的传播行为(被调用者需要事务)PROPAGATION_SUPPORTED:supported:方法支持当前事务,(被调用者支持当前事务),如果没有事务,也可以 ---- 【查询操作,有没有事务都行】PROPAGETION_REQUIRED_NEW:总是会新建一个事务,原来存在事务就挂起,直到当前事务执行完毕

还有几个,就在下面的图片中,因为使用频率不高

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSdKZelB-1641997236397)(C:UsersOMEY-PCDesktopOIP-C.jpg)]

除了告诉Spring访问的方式,还有事务的相关信息,还要知道事务的提交回滚的时机

当业务方法执行成功,没有异常抛出,当方法执行完毕的时候,spring会提交commit事务

当业务方法出现 运行时异常,spring执行回滚,调用事务管理器的rollback

当业务方法出现 非运行时异常,【需要处理】,主要时受查异常,提交事务commit

这里再另外的笔试题中提到过,异常分为RuntimeException和非运行时异常,运行时异常不能编译检查出,不需要事先处理,比如NullPointerException; 非运行时异常,也就时受查异常和Error,比如IOException、SQLException

Spring的事务是统一的模型。1)也就是管理事务的时接口PaltformTransactionManager事务管理器,使用bean指定访问的方式。 2)指定哪些类、哪些方法需要加入事务,3)同时通过TransactionDefinition指定事务的信息包括隔离级别、传播行为、超时时限等

事务实例模拟

这个实例—>购买商品、模拟用户下单,想订单表添加销售记录,从商品表减少库存【其实就是模拟的一个转账的行为】

首先创建数据库表,创建两张表,销售记录表sale、商品库存表goods

CREATE TABLE sale(
	id INT PRIMARY KEY AUTO_INCREMENT,
    gid INT NOT NULL,
    nums INT,
    FOREIGN KEY(gid) REFERENCES goods(id)
)

CREATE TABLE goods(
	id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAr(80),
    amount INT,
    price DECIMAL
)

注意,因为计算机存储浮点数是不精确的,所以叫做浮点数,所以这里的商品价格采用定点数DECIMAL

然后简单插入数据【这里是生成的,没有手写】

NSERT INTO `cfengbase`.`goods` (`id`, `name`, `amount`, `price`) VALUES ('1001', '笔记本', '70', '15.2');
INSERT INTO `cfengbase`.`goods` (`id`, `name`, `amount`, `price`) VALUES ('1002', '肥皂', '80', '7.88');

之后还是使用spring集成mybatis来创建这个实体类,这里使用前面的pom,不再导入依赖,编写是从数据持久层到业务层开始写。这里就先编写实体类,这里两张表,创建两个实体类。 注意重写toString方法,如果不重写,println会默认调用父类Object的toString方法,就是 ……@……的格式,看不到具体的值

package cfeng.domain;

public class Goods {
    private int id;
    private  String name;
    private  int amount;
    private  float price;

    public Goods() {
    }

    public Goods(int id, String name, int amount, float price) {
        this.id = id;
        this.name = name;
        this.amount = amount;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", amount=" + amount +
                ", price=" + price +
                '}';
    }
}

另外一个创建是相同的,接下来开始写dao层的部分,就是接口和对应的mapper文件

package cfeng.dao;

import cfeng.domain.Sale;

public interface SaleDao {
    //插入销售记录
    public int insertSale(Sale sale);
}







   
      INSERT INTO sale (gid,nums) VALUES (#{gid},#{nums})
   

另外一个接口的定义方式相同

package cfeng.dao;

import cfeng.domain.Goods;

public interface GoodsDao {

    //更新库存,goods表示本次购买的商品
    public int updateGoods(Goods goods);

    //查询商品的信息、主键
    public Goods selectGoods(int id);
}