默认情况下,实例的方法为事务性方法。 对于读取操作,事务配置标志设置为 。 所有其他配置都配置了纯注释,以便应用默认事务配置。 有关详细信息,请参阅 SimpleJdbcRepository 的 Javadoc。 如果需要调整存储库中声明的某个方法的事务配置,请在存储库接口中重新声明该方法,如下所示:CrudRepositoryreadOnlytrue@TransactionalSpring中文文档

CRUD 的自定义事务配置
interface UserRepository extends CrudRepository<User, Long> {

  @Override
  @Transactional(timeout = 10)
  List<User> findAll();

  // Further query method declarations
}

上述情况会导致该方法在超时 10 秒且不带标志的情况下运行。findAll()readOnlySpring中文文档

更改事务行为的另一种方法是使用通常涵盖多个存储库的外观或服务实现。 其目的是定义非 CRUD 操作的事务边界。 以下示例演示如何创建此类外观:Spring中文文档

使用外观定义多个存储库调用的事务
@Service
public class UserManagementImpl implements UserManagement {

  private final UserRepository userRepository;
  private final RoleRepository roleRepository;

  UserManagementImpl(UserRepository userRepository,
    RoleRepository roleRepository) {
    this.userRepository = userRepository;
    this.roleRepository = roleRepository;
  }

  @Transactional
  public void addRoleToAllUsers(String roleName) {

    Role role = roleRepository.findByName(roleName);

    for (User user : userRepository.findAll()) {
      user.addRole(role);
      userRepository.save(user);
    }
}

前面的示例导致调用在事务中运行(参与现有事务,如果尚未运行,则创建新事务)。 存储库的事务配置将被忽略,因为外部事务配置决定了要使用的实际存储库。 请注意,您必须显式激活或使用才能使外观工作基于注释的配置正常工作。 请注意,前面的示例假定您使用组件扫描。addRoleToAllUsers(…)<tx:annotation-driven />@EnableTransactionManagementSpring中文文档

事务查询方法

若要使查询方法具有事务性,请在定义的存储库接口中使用,如以下示例所示:@TransactionalSpring中文文档

在查询方法中使用@Transactional
@Transactional(readOnly = true)
interface UserRepository extends CrudRepository<User, Long> {

  List<User> findByLastname(String lastname);

  @Modifying
  @Transactional
  @Query("delete from User u where u.active = false")
  void deleteInactiveUsers();
}

通常,您希望将标志设置为 true,因为大多数查询方法仅读取数据。 与此相反,使用注释并覆盖事务配置。 因此,该方法的标志设置为 。readOnlydeleteInactiveUsers()@ModifyingreadOnlyfalseSpring中文文档

强烈建议将查询方法设置为事务性。 这些方法可能会执行多个查询以填充实体。 如果没有公共事务,Spring Data JDBC 将在不同的连接中执行查询。 这可能会给连接池带来过大的压力,甚至可能导致死锁,当多个方法请求新连接同时保留一个连接时。
通过设置标志来标记只读查询绝对是合理的。 但是,这并不能作为检查您不会触发操作查询(尽管某些数据库在只读事务中拒绝和语句)。 相反,该标志将作为提示传播到基础 JDBC 驱动程序,以实现性能优化。readOnlyINSERTUPDATEreadOnly
强烈建议将查询方法设置为事务性。 这些方法可能会执行多个查询以填充实体。 如果没有公共事务,Spring Data JDBC 将在不同的连接中执行查询。 这可能会给连接池带来过大的压力,甚至可能导致死锁,当多个方法请求新连接同时保留一个连接时。
通过设置标志来标记只读查询绝对是合理的。 但是,这并不能作为检查您不会触发操作查询(尽管某些数据库在只读事务中拒绝和语句)。 相反,该标志将作为提示传播到基础 JDBC 驱动程序,以实现性能优化。readOnlyINSERTUPDATEreadOnly

JDBC 锁定

Spring Data JDBC 支持锁定派生查询方法。 若要在存储库中启用对给定派生查询方法的锁定,请使用 对其进行注释。 type 的必需值提供两个值:一个是保证您正在读取的数据不会被修改,另一个是获取用于修改数据的锁。 有些数据库没有做出这种区分。 在这种情况下,这两种模式都等效于 。@LockLockModePESSIMISTIC_READPESSIMISTIC_WRITEPESSIMISTIC_WRITESpring中文文档

在派生查询方法上使用 @Lock
interface UserRepository extends CrudRepository<User, Long> {

  @Lock(LockMode.PESSIMISTIC_READ)
  List<User> findByLastname(String lastname);
}

如上所述,该方法将使用悲观的读取锁执行。 如果您使用带有 MySQL 方言的 databse,这将导致以下查询:findByLastname(String lastname)Spring中文文档

MySQL方言的结果Sql查询
Select * from user u where u.lastname = lastname LOCK IN SHARE MODE