为什么@Transactional无法与泛型一起使用

时间:2019-06-07 08:23:44

标签: spring transactions

我尝试在我的spring项目中实现事务。使用下面的代码,一切正常:

@Transactional(rollbackFor=InvocationTargetException.class, propagation = 
Propagation.REQUIRED)
public Fraud saveSingleFraud(Fraud fraud, ApplicationPrivateHeader header)
{
    @Autowired
    private FraudRepository fraudRepo;
    @Autowired
    private FraudTieRepository fraudTieRepo;

    // first insert
    fraudRepo.save(fraud);  

    FraudTie fraudTie = new FraudTie();
             fraudTie.setId("6666-6666-6666");
             fraudTie.setDbPartKey("0112");
             fraudTie.setType("P");
             fraudTie.setFraudId("00ed644e-6666-b371");
    // second insert (different repo)   
    fraudTieRepo.save(fraudTie);
}

但是我的实现不是很酷。我需要使用

进行事务处理

控制器类

@RestController
public class FraudController {
    @Autowired
    private FraudService fraudService;
    @PostMapping("testInsertfraud")
    public Fraud saveFraudTie(  @RequestAttribute(name = HeaderFactory.HEADER_REQUEST_ATTRIBUTE)            final ApplicationPrivateHeader header,
                            @RequestParam(name="dbPartKey",         required = true)    @Min(4) @Max(4)     final String dbPartKey,
                            @RequestParam(name="trxId",             required = true)    @Min(36) @Max(36)   final String trxId,
                            @RequestParam(name="jobId",             required = false)   @Min(36) @Max(36)   final String jobId,
                            @RequestParam(name="jobDbpartKey",      required = false)   @Min(4) @Max(4)     final String jobDbpartKey,
                            @RequestParam(name="dossierId",         required = false)   @Min(36) @Max(36)   final String dossierId,
                            @RequestParam(name="dossierDbPartKey",  required = false)   @Min(4) @Max(4)     final String dossierDbPartKey,
                            @RequestParam(name="certainty",         required = true)    @Min(1) @Max(1)     final String certainty,
                            @RequestParam(name="isActive",          required = true)    @Min(1) @Max(1)     final    int isActive){

      Fraud fraud = new Fraud();
            fraud.setDbPartKey(dbPartKey);
            fraud.setTrxId(trxId);
            fraud.setJobId(jobId);
            fraud.setJobDbpartKey(jobDbpartKey);
            fraud.setDossierId(dossierId);
            fraud.setDossierDbPartKey(dossierDbPartKey);
            fraud.setCertainty(certainty);
            fraud.setIsActive(isActive);

            fraud.setCreationTimestamp(AuthParser.getCalendar(System.currentTimeMillis()));
            fraud.setEditTimestamp(AuthParser.getCalendar(System.currentTimeMillis()));
            fraud.setCreationApplication(header.getAppName());
            fraud.setEditApplication(header.getAppName());
            fraud.setCreationUserId(header.getUserID());
            fraud.setEditUserId(header.getUserID());

        return  fraudService.saveSingleFraud(fraud, header);
    }
}

服务等级

@Service
public class FraudService {
    @Autowired
    ActionRetriever retriever;
    @Autowired
    private FraudRepository fraudRepo;

    private Action<SingleEntityContext<Fraud, String>, Fraud>       actionSaveFraud;
    private Elaboration<SingleEntityContext<Fraud, String>, Fraud>  saveElaborationFraud;

    @PostConstruct
    void init() {

        actionSaveFraud = retriever.getActionBean("crud/saveEntity");
        saveElaborationFraud = new Elaboration<>(this.actionSaveFraud);
    }

    @Transactional(rollbackFor=Exception.class, propagation = Propagation.REQUIRED)
    public Fraud saveSingleFraud(Fraud fraud, ApplicationPrivateHeader header){

        // first insert
        Fraud fraude = saveElaborationFraud.execute(new SingleEntityContext<>(header, fraudRepo, fraud));

        FraudTie fraudTie = new FraudTie();
        fraudTie.setId("6666-6666-6666-6666-9999");
        fraudTie.setDbPartKey("0112");
        fraudTie.setType("P");
        fraudTie.setFraudId("00ed644e-6666-48fa-b371-d53dfbb4ad8c");
        // second insert        
        fraudTie = fraudTieRepo.save(fraudTie);
    }
}

细化类

@RequiredArgsConstructor
public class Elaboration<C extends BaseContext, T> {

    @NonNull
    private final Action<? super C, T>                         action;
    private final List<AdditionalAction<? super C, ? super T>> additionalActions = new ArrayList<>();

    public final void addAction(final AdditionalAction<? super C, ? super T> action) {
        this.additionalActions.add(action);
    }

    public T execute(final C context) throws ServiceInvocationException {
        final ServiceParameter<? super C>  contextParameter  = new ServiceParameter<>(context);
        final ServiceParameter<T>          response          = this.action.apply(contextParameter);
        final List<ServiceParameter<Void>> additionalResults = new ArrayList<>();
        for (final AdditionalAction<? super C, ? super T> additionalAction : this.additionalActions) {
            additionalResults.add(additionalAction.apply(contextParameter, response));
        }
        for (final ServiceParameter<Void> serviceParameter : additionalResults) {
            try {
                serviceParameter.get();
            } catch (final ServiceInvocationException e) {
                // This is OK and already logged, going to next action
            }
        }
        return response.get();
    }

}

SingleEntityContext类

 @Getter
 public class SingleEntityContext<T, K extends Serializable> extends RepoContext<T, K>  {

    private T entity;

    public SingleEntityContext(String id, String user, String appName, CrudRepository<T, K> repo, T entity) {
        super(id, user, appName, repo);
        this.entity = entity;
    }

    public SingleEntityContext(ApplicationPrivateHeader header, CrudRepository<T, K> repo, T entity) {
        super(header, repo);
        this.entity = entity;
    }

    public SingleEntityContext(BaseContext ctx, CrudRepository<T, K> repo, T entity) {
        super(ctx, repo);
        this.entity = entity;
    }

}

动作类

@Configuration
public class CrudActionFactory {

    @Bean("crud/saveEntity")
    public <T, K extends Serializable> Action<SingleEntityContext<T, K>, T> saveEntity() throws ServiceInstantiationException{
        return ActionsFactory.standard(this.eventPublisher, "crud/saveEntity", context -> context.getRepo().save(context.getEntity()));
    }
}

现在,无论是否有@Transaction,都将保存Fraud和FraudTie,但不保存在事务中,因此当第二个查询运行时,第一个查询已被提交。

我也尝试过:(同样,查询有效,但不能在事务中完成)

@Transactional(rollbackFor=InvocationTargetException.class, propagation = Propagation.REQUIRED)
public Fraud saveSingleFraud(Fraud fraud, ApplicationPrivateHeader header) throws ServiceInvocationException{

    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);

    return (Fraud) transactionTemplate.execute(new TransactionCallback() {
        public Fraud doInTransaction(TransactionStatus status) {

            Fraud fraude  = saveElaborationFraud.execute(new SingleEntityContext<>(header, fraudRepo, fraud));
            System.out.println(fraude.getId());
            FraudTie fraudTie = new FraudTie();
            fraudTie.setId("6666-6666-6666");
            fraudTie.setDbPartKey("0112");
            fraudTie.setType("P");
            fraudTie.setFraudId("00ed644e-6666-b371");

            fraudTie = fraudTieRepo.save(fraudTie);

            return fraude;
        }
    });

}

此处控制台日志:

2019-06-07 09:41:23,186 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] to thread [http-nio-8080-exec-10]
2019-06-07 09:41:23,244 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] bound to thread [http-nio-8080-exec-10]
2019-06-07 09:41:23,253 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@5f33c1ab] for key [HikariDataSource (HikariPool-1)] to thread [http-nio-8080-exec-10]
2019-06-07 09:41:23,254 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:272  ) - Initializing transaction synchronization
2019-06-07 09:41:23,268 TRACE [http-nio-8080-exec-10         ] (ringframework.transaction.interceptor.TransactionInterceptor:488  ) - Getting transaction for [it.mercury.ws.frame.common.request.FraudService.saveSingleFraud]
2019-06-07 09:41:24,819 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] bound to thread [http-nio-8080-exec-10]
2019-06-07 09:41:24,821 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@5f33c1ab] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8080-exec-10]
2019-06-07 09:41:24,852 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@d8cf012] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] to thread [pool-27-thread-1]
2019-06-07 09:41:24,920 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@3bfc38cb] for key [HikariDataSource (HikariPool-1)] to thread [pool-27-thread-1]
2019-06-07 09:41:24,920 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.orm.jpa.EntityManagerHolder@2c952477] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] to thread [pool-27-thread-1]
2019-06-07 09:41:24,920 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:272  ) - Initializing transaction synchronization
2019-06-07 09:41:24,922 TRACE [pool-27-thread-1              ] (ringframework.transaction.interceptor.TransactionInterceptor:488  ) - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-06-07 09:41:24,984 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@2c952477] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] bound to thread [pool-27-thread-1]
Hibernate: 
    select
        fraud0_.dbPartKey as dbPartKe1_5_0_,
        fraud0_.id as id2_5_0_,
        fraud0_.certainty as certaint3_5_0_,
        fraud0_.creationApplication as creation4_5_0_,
        fraud0_.creationTimestamp as creation5_5_0_,
        fraud0_.creationUserId as creation6_5_0_,
        fraud0_.dossierDbPartKey as dossierD7_5_0_,
        fraud0_.dossierId as dossierI8_5_0_,
        fraud0_.editApplication as editAppl9_5_0_,
        fraud0_.editTimestamp as editTim10_5_0_,
        fraud0_.editUserId as editUse11_5_0_,
        fraud0_.isActive as isActiv12_5_0_,
        fraud0_.jobDbpartKey as jobDbpa13_5_0_,
        fraud0_.jobId as jobId14_5_0_,
        fraud0_.trxId as trxId15_5_0_ 
    from
        Fraud fraud0_ 
    where
        fraud0_.dbPartKey=? 
        and fraud0_.id=?
2019-06-07 09:41:25,153 TRACE [pool-27-thread-1              ] (ringframework.transaction.interceptor.TransactionInterceptor:516  ) - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
Hibernate: 
    insert 
    into
        Fraud
        (certainty, creationApplication, creationTimestamp, creationUserId, dossierDbPartKey, dossierId, editApplication, editTimestamp, editUserId, isActive, jobDbpartKey, jobId, trxId, dbPartKey, id) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2019-06-07 09:41:25,230 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:331  ) - Clearing transaction synchronization
2019-06-07 09:41:25,231 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.orm.jpa.EntityManagerHolder@2c952477] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] from thread [pool-27-thread-1]
2019-06-07 09:41:25,231 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@3bfc38cb] for key [HikariDataSource (HikariPool-1)] from thread [pool-27-thread-1]
2019-06-07 09:41:25,232 TRACE [pool-27-thread-1              ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@d8cf012] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] from thread [pool-27-thread-1]
20470f46-67da-ba25
2019-06-07 09:41:25,239 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:193  ) - Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@d8cf012] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] to thread [http-nio-8080-exec-10]
2019-06-07 09:41:25,240 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] bound to thread [http-nio-8080-exec-10]
2019-06-07 09:41:25,240 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@5f33c1ab] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8080-exec-10]
2019-06-07 09:41:25,241 TRACE [http-nio-8080-exec-10         ] (ringframework.transaction.interceptor.TransactionInterceptor:488  ) - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-06-07 09:41:25,247 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:140  ) - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] bound to thread [http-nio-8080-exec-10]
Hibernate: 
    select
        fraudtie0_.dbPartKey as dbPartKe1_6_0_,
        fraudtie0_.id as id2_6_0_,
        fraudtie0_.fraudId as fraudId3_6_0_,
        fraudtie0_.type as type4_6_0_ 
    from
        FraudTie fraudtie0_ 
    where
        fraudtie0_.dbPartKey=? 
        and fraudtie0_.id=?
2019-06-07 09:41:25,253 TRACE [http-nio-8080-exec-10         ] (ringframework.transaction.interceptor.TransactionInterceptor:516  ) - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2019-06-07 09:41:25,253 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@d8cf012] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] from thread [http-nio-8080-exec-10]
2019-06-07 09:41:25,254 TRACE [http-nio-8080-exec-10         ] (ringframework.transaction.interceptor.TransactionInterceptor:516  ) - Completing transaction for [it.mercury.ws.frame.common.request.FraudService.saveSingleFraud]
Hibernate: 
    insert 
    into
        FraudTie
        (fraudId, type, dbPartKey, id) 
    values
        (?, ?, ?, ?)
2019-06-07 09:41:25,264 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:331  ) - Clearing transaction synchronization
2019-06-07 09:41:25,265 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@5f33c1ab] for key [HikariDataSource (HikariPool-1)] from thread [http-nio-8080-exec-10]
2019-06-07 09:41:25,424 TRACE [http-nio-8080-exec-10         ] (mework.transaction.support.TransactionSynchronizationManager:243  ) - Removed value [org.springframework.orm.jpa.EntityManagerHolder@47a4166a] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@e3ba1c5] from thread [http-nio-8080-exec-10]

我认为该问题与泛型有关,请帮助我找到解决方案。

0 个答案:

没有答案