【Spring】JDBC、AOP、事务

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【Spring】JDBC、AOP、事务

1. Spring中JDBC简介

个人感觉Spring中的JDBC简化了我们之前手写JDBC的步骤,实现了代码的简洁与条理性

如下所示:

public int insert() {
    String sql = "insert into test(id, name)values(?,?)";
    return jdbcTemplate.update(sql, "1", "2");
  }
  public int update() {
    String sql = "update test set name = ? where id = ?";
    return jdbcTemplate.update(sql, "3", "1");
  }
  public int delete(String id) {
    String sql = "delete from test where id = ?";
    return jdbcTemplate.update(sql, id);
  }
  public List<TestModel> selectList() {
    String sql = "select id, name from test where id=?";
    return jdbcTemplate.query(sql, new Object[] { 15 }, new ModelMapper());
  }

基本直接一条语句就可以进行配置,完成数据库的增删改查

因此,我们来看一下具体的配置方法及应用

2. Spring的配置

2.1 pom.xml

首先就是总体xml文件的配置了,主要引进依赖及各种包

== 需要注意的是:我们spring-webmvcspring-jdbc的版本必须保持一致==

z<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>situ</groupId>
  <artifactId>test3</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>test3 Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <!-- 依赖 -->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.20</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.json/json -->
    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
      <version>20160810</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.1</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>test3</finalName>
  </build>
</project>

2.2 数据库连接池

我们在配置完总体xml之后,需要进行数据源的注入

在Spring中有3中注入的方法:JDBC、C3P0、DBCP

2.2.1 JDBC连接池

对于JDBC来说,他属于Spring的内置连接池

配置条件如下:

<!-- 引入属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 配置Spring内置的连接池 -->
       <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <!-- 引入属性文件的值 -->            
         <property name="driverClassName" value="${driverClass}"></property>
          <property name="url" value="${jdbcUrl}"></property>
           <property name="username" value="${user}"></property>
           <property name="password" value="${password}"></property>
       </bean>
       <!-- 配置spring的JDBC的模版 -->
       <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
           <property name="dataSource" ref="dataSource"></property>
       </bean>

2.2.2 C3P0连接池

<!-- 引入属性文件 -->
    <context:property-placeholder location="classpath:JDBC.properties"/>
    <!-- 配置C3P0连接池 -->
       <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!-- 引入属性文件的值 -->            
         <property name="driverClass" value="${driverClass}"></property>
          <property name="jdbcUrl" value="${jdbcUrl}"></property>
           <property name="user" value="${user}"></property>
           <property name="password" value="${password}"></property>
    </bean>
       <!-- 配置spring的JDBC的模版 -->
       <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
           <property name="dataSource" ref="dataSource"></property>
       </bean>

2.2.3 DBCP连接池

<!-- 引入属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 配置DBCP连接池 -->
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 引入属性文件的值 -->            
         <property name="driverClassName" value="${driverClass}"></property>
          <property name="url" value="${jdbcUrl}"></property>
           <property name="username" value="${user}"></property>
           <property name="password" value="${password}"></property>
       </bean>
       <!-- 配置spring的JDBC的模版 -->
       <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
           <property name="dataSource" ref="dataSource"></property>
       </bean>

2.2.4 jdbc.properties文件

user=root
password=123456
minPoolSize=5
maxPoolSize=20
initialPoolSize=5
driverClass=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql://127.0.0.1:3308/work?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true

2.2.4 总配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd"
  default-autowire="byName">
  <context:annotation-config />
  <context:component-scan base-package="service" />
  <context:property-placeholder
    location="classpath:JDBC.properties" />
  <!-- 数据源 -->
  <!-- <bean id="dataSource" -->
  <!-- class="org.springframework.jdbc.datasource.DriverManagerDataSource"> -->
  <!-- <property name="driverCLassName" value="${driverClass}" /> -->
  <!-- <property name="url" value="${jdbcUrl}" /> -->
  <!-- <property name="username" value="${user}" /> -->
  <!-- <property name="password" value="${pass}" /> -->
  <!-- </bean> -->
  <bean id="dataSource"
    class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${driverClass}" />
    <property name="jdbcUrl" value="${jdbcUrl}" />
    <property name="user" value="${user}" />
    <property name="password" value="${password}" />
    <property name="minPoolSize" value="${minPoolSize}"></property>
    <property name="maxPoolSize" value="${maxPoolSize}"></property>
    <property name="initialPoolSize" value="${initialPoolSize}"></property>
  </bean>
  <bean id="springJdbc1" class="service.SpringJdbc1"></bean>
  <!--生成JdbcTemplate -->
  <!--直接使用XML进行注入 -->
  <bean id="jdbcTemplate2"
    class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
  </bean>
  <bean id="SpringDao" class="service.SpringDao"></bean>
  <bean id="Dao1" class="service.Dao1"></bean>
</beans>

3. Java端

3.1 TestModel

最底层的Model层,用来实现类的封装

package service;
public class TestModel {
  private String id;
  private String name;
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  @Override
  public String toString() {
    return "TestModel [id=" + id + ", name=" + name + "]";
  }
}

3.2 SpringDao

这一层主要是利用JdbcTemplate提供的增删改查来实现对数据库的操作

3.2.1 注入的操作

@Autowired
  @Qualifier("jdbcTemplate2")
  private JdbcTemplate jdbcTemplate;

这里使用Autowired + Qualifier(“jdbcTemplate2”),是将我们在context3中进行的XML注入拿过来使用注入private JdbcTemplate jdbcTemplate;这个里面

<bean id="jdbcTemplate2"
    class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
  </bean>

3.2.2 增删改的操作

public int insert() {
    String sql = "insert into test(id, name)values(?,?)";
    return jdbcTemplate.update(sql, "1", "2");
  }
  public int update() {
    String sql = "update test set name = ? where id = ?";
    return jdbcTemplate.update(sql, "3", "1");
  }
  public int delete(String id) {
    String sql = "delete from test where id = ?";
    return jdbcTemplate.update(sql, id);
  }

3.3.3 查找的操作

对于查找来说,使用的是jdbcTemplate.query

我们来看一下:

第一个参数sql:数据库语句

第二个参数:一个Object的数组,也就是填充我们的问号

第三个参数:ModelMapper(映射)

public List<TestModel> selectList() {
    String sql = "select id, name from test where id=?";
    return jdbcTemplate.query(sql, new Object[] { 15 }, new ModelMapper());
  }

我们重点来看一下这个映射

对于映射而言,我们首先要知道这是干什么的?

我们知道,查询和增删改最大的操作不同就是它多一步返回ModelList值的操作,也就是ResultSet rs的获取

所以,我们需要获取这个ModelList,来进行返回

import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class ModelMapper implements RowMapper<TestModel> {
  // 映射ORM
  // 查询出来的值来进行赋值
  // 查询几条记录 就会映射几次
  public TestModel mapRow(ResultSet rs, int rowNum) throws SQLException {
    TestModel testModel = new TestModel();
    testModel.setId(rs.getString("id"));
    testModel.setName(rs.getString("name"));
    return testModel;
  }
}

因为我们返回的是一个集合,所以,集合里面有几条数据,就映射几次

另一种写法(内部类)

public List<TestModel> selectList2() {
    String sql = "select id, name from test where 1=1";
    return jdbcTemplate.query(sql, new Object[] { 15 }, new ModelMapper() {
      public TestModel mapRow(ResultSet rs, int rowNum) throws SQLException {
        TestModel testModel = new TestModel();
        testModel.setId(rs.getString("id"));
        testModel.setName(rs.getString("name"));
        return testModel;
      }
    });
  }

当然,我们也进行查询后返回别的值,如下:

public void queryForObject() {
    String sql = "select id, name from test where id=?";
    TestModel model = jdbcTemplate.queryForObject(sql, new Object[] { 15 }, new ModelMapper());
    System.out.println(model);
    String sql2 = "select id, name from test where id=?";
    String name = jdbcTemplate.queryForObject(sql2, new Object[] { 1 }, String.class);
    System.out.println(name);
  }

第一种利用queryForObject来返回一个Model进行输出

第二种利用String.class加载String的类,进行反射

3.3 Main(类似Service层,主要进行测试用)

  • 通过ApplicationContext context = new ClassPathXmlApplicationContext("context3.xml");创里连接
  • 获取SpringDao的对象context.getBean("SpringDao")
  • 最后,调用dao.test()进行输出
<bean id="SpringDao" class="service.SpringDao"></bean>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
  public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("context3.xml");
    SpringDao dao = (SpringDao) context.getBean("SpringDao");
    dao.test();
    // 输出111
  }
}

4. AOP、事务

== AOP是个啥?==

专业术语:面向切面编程

通俗提懂:我们把每一个层分开,在每一个层进行操作,如事务

== 事务是啥呢?==

这里简单说一下,我所理解的事务也就是:

比如一个部门表,一个成员表,当部门表被删除时,我们也要删除相对应的成员信息,也就是执行两条SQL语句

假如这时候我们把部门表给删除了,我们再去删除成员表中的信息时,出现了一点小意外,导致我们成员表信息没办法删除,这时候就尴尬了~

部门表已经没了,可成员对应的部门还存在,这。。。。有点匪夷所思

所以,我们用事务来解决这个问题

我们把所有的要执行的SQL语句放在一个事务中,假如其中有一个报错,则直接进行回滚,我们之前执行的所有的操作语句都还原,这样就可以避免上述尴尬情况的发生。

4.1 事务的配置

对于事务来说,我们也需要进行文件的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd"
  default-autowire="byName">
  <bean id="dao1" class="service.Dao1" />
  <bean id="springDao" class="service.SpringDao" />
  <bean id="service1" class="service.Serivce1" />
  <!-- 事务管理器 -->
  <bean id="transactionManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <!-- 需要管理的数据源 -->
  </bean>
  <tx:advice id="advice"
    transaction-manager="transactionManager">
    <tx:attributes>
      <!-- <tx:method name="*" propagation="REQUIRED" /> -->
      <tx:method name="delete*" propagation="REQUIRED" />
      <tx:method name="update*" propagation="REQUIRED" />
      <tx:method name="insert*" propagation="REQUIRED" />
    </tx:attributes>
  </tx:advice>
  <!-- 用切点把事务切进去 -->
  <aop:config>
    <aop:pointcut expression="execution(* service.*.*(..))"
      id="pointcut" />
    <aop:advisor advice-ref="advice" pointcut-ref="pointcut" />
  </aop:config>
</beans>

第一部分,也就是事务管理器,这个是干啥的呢?

我们在上面从数据池中拿出来的东西,也就是数据源,要在这进行管理

这里我们使用了别的xml文件的内容,我们怎么可以使用的呢?

建立一个spring.xml,将两个xml文件合成一个

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd"
  default-autowire="byName">
  <context:annotation-config />
  <context:component-scan base-package="service" />
  <import resource="context3.xml"></import>
  <import resource="test3.xml"></import>
</beans>

第二部分,我们规定的操作,这里注意一下:name="delete*"这个*号的意思,也就以delete开头所有方法

第三部分,利用AOP切片,将事务切入进去,execution(* service.*.*(..)) 意思为:service包下的任意类下的任意方法的任意参数

4.2 配置另外的类

和上面差不多,主要就是修改一下Dao层里关于SQL语句的书写

我们在定义一个Model2,一个Dao2

Model2

package service;
public class TestModel2 {
  private String id;
  private String name;
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  @Override
  public String toString() {
    return "TestModel [id=" + id + ", name=" + name + "]";
  }
}

Dao2

package service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
public class Dao1 {
  @Autowired
  @Qualifier("jdbcTemplate2")
  private JdbcTemplate jdbcTemplate;
  public void test1() {
    System.out.println("111");
  }
  public int insert() {
    String sql = "insert into test1(id, name)values(?,?)";
    return jdbcTemplate.update(sql, "1", "2");
  }
  public int update() {
    String sql = "update test1 set name = ? where id = ?";
    return jdbcTemplate.update(sql, "3", "1");
  }
  public int delete(String id) {
    String sql = "delete from test1 where id = ?";
    return jdbcTemplate.update(sql, id);
  }
  // 三个参数
  // sql : SQL语句
  // Object : 你要赋值的一个数组
  public List<TestModel> selectList() {
    String sql = "select id, name from test1 where id=?";
    return jdbcTemplate.query(sql, new Object[] { 15 }, new ModelMapper());
  }
  // 内部类的写法
  public List<TestModel> selectList2() {
    String sql = "select id, name from test1 where 1=1";
    return jdbcTemplate.query(sql, new Object[] { 15 }, new ModelMapper() {
      public TestModel mapRow(ResultSet rs, int rowNum) throws SQLException {
        TestModel testModel = new TestModel();
        testModel.setId(rs.getString("id"));
        testModel.setName(rs.getString("name"));
        return testModel;
      }
    });
  }
  public void queryForObject() {
    String sql = "select id, name from test1 where id=?";
    TestModel model = jdbcTemplate.queryForObject(sql, new Object[] { 15 }, new ModelMapper());
    System.out.println(model);
    String sql2 = "select id, name from test1 where id=?";
    String name = jdbcTemplate.queryForObject(sql2, new Object[] { 1 }, String.class);
    System.out.println(name);
  }
}

4.3 事务的实现

到了最后一步,也就是真正实现我们的事务

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Serivce1 {
  @Autowired
  private SpringDao springDao;
  @Autowired
  private Dao1 dao1;
  public void delete(String id) {
    dao1.delete(id);
    springDao.delete(id);
  }
  public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Serivce1 serivce1 = (Serivce1) context.getBean("service1");
    serivce1.delete("1");
  }
}

对于下面这两段代码,主要就是注入Dao1和SpringDao

@Autowired
  private SpringDao springDao;
  @Autowired
  private Dao1 dao1;

下面代码

  • 调用spring.xml文件
  • 获取service1的实例化
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Serivce1 serivce1 = (Serivce1) context.getBean("service1");
    serivce1.delete("1");
  }

最后事务成功实现

4.4 事务的验证

public int delete(String id) {
    if (id.equals("1")) {
      int n = 1 / 0;
    }
    String sql = "delete from test1 where id = ?";
    return jdbcTemplate.update(sql, id);
  }

将Dao的删除改为以上代码,即可验证其合理性


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
19天前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
20天前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
253 0
|
4月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
|
1月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
1月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
|
1月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
1月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
6月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
139 0
|
4月前
|
人工智能 Java 数据库连接
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
236 10
|
3月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
300 1