---
# System prepended metadata

title: '`@Transactional` Restrictions'
tags: [chatgpt]

---

# `@Transactional` Restrictions

[TOC]

###### tags: `chatgpt`

---

## Spring 的 `@Transactional` 只能用在 service layer 的 public 方法嗎

在 Spring 中，`@Transactional` 注解通常用于事务处理。当一个方法使用了 `@Transactional` 注解时，Spring 将会在该方法执行期间开启一个事务，如果方法执行成功则提交事务，否则回滚事务。

默认情况下，`@Transactional` 注解只会应用在 `public` 访问级别的方法上。这是因为 Spring 使用 AOP 技术来为带有 `@Transactional` 注解的方法创建一个代理对象，并在代理对象中织入事务处理逻辑。而只有 `public` 方法才能被代理对象调用，因此只有 `public` 方法才能被 `@Transactional` 注解正确处理。

但是，如果你需要在非 `public` 方法上使用 `@Transactional` 注解，也是可以的。你可以使用 Spring 的 AspectJ 支持来实现，需要进行以下步骤：

1. 在 Spring 配置文件中开启 AspectJ 支持：`<aop:aspectj-autoproxy/>`。

1. 在 `@Transactional` 注解中添加 `access` 属性，并指定所需的访问级别，例如 `@Transactional(access = AccessType.PROTECTED)`。

需要注意的是，使用 AspectJ 支持可能会影响性能，因为它需要在编译时生成额外的代码。因此，只有在需要的情况下才应该使用非 `public` 访问级别的 `@Transactional` 注解。

## 使用 Spring 的 `JdbcTemplate` 做查詢，若其中一個查詢參數為列舉值要怎麼寫

如果你想在使用 Spring 的 `JdbcTemplate` 进行查询时，其中一个查询参数是枚举值，可以按照以下步骤进行编写：

1. 在 SQL 查询语句中使用占位符来表示枚举值的位置，例如：

```sql
SELECT * FROM my_table WHERE status = ?
```

这里假设 `status` 是一个枚举类型的列。

2. 在查询方法中，将枚举值转换为相应的字符串，然后将其传递给 `JdbcTemplate` 的查询方法，例如：

```java
public List<MyEntity> findByStatus(MyEnum status) {
	String sql = "SELECT * FROM my_table WHERE status = ?";
	String statusStr = status.name(); // 枚举值转换为字符串
	return jdbcTemplate.query(
		sql,
		new BeanPropertyRowMapper<>(MyEntity.class),
		statusStr
	);
}
```

在上面的示例中，`status.name()` 方法返回枚举值的字符串表示形式，该字符串与数据库中存储的值相匹配。

需要注意的是，在使用 `JdbcTemplate` 进行查询时，应该始终使用占位符来表示查询参数，以避免 SQL 注入攻击。同时，应该尽可能地使用类型安全的查询参数，以避免类型转换错误。
