【Spring Framework】Spring 事务使用的完整示例

为了详细展示 Spring 事务的使用,我将提供一个完整的示例,包括配置、代码和说明。这将涵盖以下几个方面:

  1. 数据库配置:包括数据源和事务管理器的配置。
  2. 实体类:用于数据库操作的数据模型。
  3. DAO 层:数据访问对象,用于执行数据库操作。
  4. 服务层:业务逻辑层,包含事务管理的业务方法。
  5. 配置:包括 Java 配置和 XML 配置示例。
  6. 测试:如何测试事务管理的功能。

示例项目结构

假设我们有一个简单的 Spring 项目,用于处理用户的 CRUD 操作,以下是示例项目的主要结构:

src/main/java
  └── com
      └── example
          ├── config
          │   ├── AppConfig.java
          │   └── TransactionConfig.xml
          ├── dao
          │   └── UserDao.java
          ├── entity
          │   └── User.java
          ├── service
          │   └── UserService.java
          └── test
              └── UserServiceTest.java

一、数据库配置

1. 数据源配置

Java 配置 (AppConfig.java)

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example") // 扫描指定包下的组件
public class AppConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/testdb");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

XML 配置 (TransactionConfig.xml)

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 数据源配置 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- JdbcTemplate 配置 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 事务管理器配置 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 启用事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 扫描包路径 -->
    <context:component-scan base-package="com.example"/>
</beans>

二、实体类

User.java

package com.example.entity;

public class User {
    private int id;
    private String username;
    private String password;

    // Getters and Setters
    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

三、DAO 层

UserDao.java

package com.example.dao;

import com.example.entity.User;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void createUser(User user) {
        String sql = "INSERT INTO users (username, password) VALUES (?, ?)";
        jdbcTemplate.update(sql, user.getUsername(), user.getPassword());
    }

    public User getUserById(int id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) -> {
            User user = new User();
            user.setId(rs.getInt("id"));
            user.setUsername(rs.getString("username"));
            user.setPassword(rs.getString("password"));
            return user;
        });
    }

    public void updateUser(User user) {
        String sql = "UPDATE users SET username = ?, password = ? WHERE id = ?";
        jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), user.getId());
    }

    public void deleteUser(int id) {
        String sql = "DELETE FROM users WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }
}

四、服务层

UserService.java

package com.example.service;

import com.example.dao.UserDao;
import com.example.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    public void createUser(User user) {
        userDao.createUser(user);
        // Simulate an exception to test rollback
        if ("error".equals(user.getUsername())) {
            throw new RuntimeException("Simulated exception");
        }
    }

    @Transactional
    public void updateUser(User user) {
        userDao.updateUser(user);
        // Simulate an exception to test rollback
        if ("error".equals(user.getUsername())) {
            throw new RuntimeException("Simulated exception");
        }
    }
}

五、测试

UserServiceTest.java

package com.example.test;

import com.example.config.AppConfig;
import com.example.entity.User;
import com.example.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;

import static org.junit.jupiter.api.Assertions.assertThrows;

public class UserServiceTest {

    @Test
    public void testCreateUserWithTransaction() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);

        User user = new User();
        user.setUsername("normaluser");
        user.setPassword("password");

        // Test normal behavior
        userService.createUser(user);

        // Test exception and rollback
        User errorUser = new User();
        errorUser.setUsername("error");
        errorUser.setPassword("password");

        assertThrows(RuntimeException.class, () -> {
            userService.createUser(errorUser);
        });
    }

    @Test
    public void testUpdateUserWithTransaction() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);

        User user = new User();
        user.setId(1); // assuming user with ID 1 exists
        user.setUsername("updateduser");
        user.setPassword("newpassword");

        // Test normal behavior
        userService.updateUser(user);

        // Test exception and rollback
        User errorUser = new User();
        errorUser.setId(1); // assuming user with ID 1 exists
        errorUser.setUsername("error");
        errorUser.setPassword("newpassword");

        assertThrows(RuntimeException.class, () -> {
            userService.updateUser(errorUser);
        });
    }
}

六、总结

  • 配置:数据库连接和事务管理器的配置可以使用 Java 配置或 XML 配置,根据项目需求选择合适的方式。
  • 实体类:定义了与数据库表映射的 Java 类。
  • DAO 层:负责具体的数据库操作,如创建、读取、更新和删除(CRUD)操作。
  • 服务层:封装业务逻辑,并通过 @Transactional 注解来管理事务。
  • 测试:验证事务管理是否按预期工作,测试正常情况下和异常情况下的事务回滚行为。

通过上述示例,您可以清楚地了解如何在 Spring 框架中配置和使用事务管理。这个示例展示了如何通过 Java 配置和 XML 配置来设置事务管理器,如何在服务层使用事务管理,以及如何编写测试用例来验证事务的行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值