## 四种事务传递类型

支持以下四种事务传递类型：

| 类型          | 说明                                                         |
| ------------- | ------------------------------------------------------------ |
| SUPPORTS      | 如果当前存在一个事务，则支持当前事务，如果没有事务则不开启。 |
| REQUIRED      | 如果当前存在一个事务，则支持当前事务，如果没有事务则开启。   |
| REQUIRES_NEW  | 总是开启一个新的事务。如果一个事务存在，则将当前存在的事务挂起。 |
| NOT_SUPPORTED | 总是非事务地执行，并挂起任何存在的事务。                     |

若当前不存在事务，则默认为NOT_SUPPORTED类型，每个API的调用为独立事务(每次调用自动提交，发生错误自动回滚)。



## 快速上手

```java
try (TXHandle h = TX.required("fi_voucher_submit")) {
	try {
		// ...
	} catch (Throwable e) {
		h.markRollback();
		throw e;
	}
}
```

所有SQL异常，在DB里已经标识当前事务为markRollback，在事务结束时执行rollback。

但是业务异常，用户应自行设置是否要rollback (markRollback)。



## 事务接口

接口类：`kd.bos.db.TX`

```java
public static TXHandle notSupported()
public static TXHandle notSupported(String tag)
public static TXHandle required()
public static TXHandle required(String tag)
public static TXHandle requiresNew()
public static TXHandle requiresNew(String tag)
```



## 获取当前事务类型

`kd.bos.db.tx.Propagation`

```java
Propagation p = TX.getPropagation();
```



## 嵌套事务

事务可嵌套。

```java
try (TXHandle h1 = TX.requiresNew()) {
	try {
		// 在这里执行的，有事务。

		try (TXHandle h2 = TX.notSupported()) {
			// 在这里执行的，无事务。
		}

		// 在这里执行的，有事务。
	} catch (Throwable e) {
		h1.markRollback();
		throw e;
	}
}
```

注意：在某个事务内（NOT_SUPPORTED除外）查询出的DataSet，不能在事务外层使用(事务已结束)。



## 禁止跨库写

一个事务里，禁止写两个或以上的物理库，DB检测到则抛异常。



## 禁止跨节点事务

跨微服务节点的事务，在API调用时将被检测并抛异常。

**禁止跨节点事务说明**

-  微服务A调用微服务B，若A中有事务，则B不可有事务。


```sequence
微服务A->微服务B: API调用B
Note left of 微服务A: A有事务
Note right of 微服务B: B不可有事务


```

- 微服务A调用微服务B，微服务B再调用微服务C。


若A中有事务，B无事务，C也不可有事务。

```sequence
微服务A->微服务B: API调用B
Note left of 微服务A: A有事务
Note left of 微服务B: B无事务
微服务B->微服务C: API调用C
Note right of 微服务C: C不可有事务
```

<font color='red'>存在跨库写、跨节点事务的场景，请改用MQ实现，把操作流程化。</font>


