如何在@Transactional模式下强制提交实体

时间:2018-06-02 06:38:32

标签: java hibernate jdbc spring-data-jpa spring-jdbc

我正在使用Spring数据jpa和jdbc(使用entityManager.unwrap(Session.class))连接。
我的请求流经3方法。第1 - >第二 - >第三 第1和第3个用@Transactional注释 在第一和第二方法中通过JPA CRUD存储库保存实体 在第三种方法中使用基本的jdbc查询来检索第二种方法中保存的值 正如我们在@Transaction中所知,在JPA提交事务之前,实体不会提交到数据库 我在第二种方法中也使用了saveAndFlush,但是看不到使用jdbc查询在方法3中检索更新的值。

第一种方法 - 更新()

@Transactional
@Override
public ApiResponse update(RequestInput input) {
    ApiResponse response = doRestOfWork(input);   // calling 2nd method
    // .... some other entity save....
}

第二种方法 - doRestOfWork():设置status = true并调用saveAndFlush方法

@Override
public ApiResponse doRestOfWork(Request request) {
    Insight insight = insightRepository.findOne(request.getTypeId());
    insight.setStatus(true);
    insightRepository.saveAndFlush(insight);

    processOperation();    // calling 3rd method
}

第三种方法 - processOperation():通过jdbc连接检索更新的状态值。

@Transactional
public void processOperation() {
Connection conn = null;
        SessionImplementor sessionImpl = (SessionImplementor) entityManager.unwrap(Session.class);
        try {
            conn = sessionImpl.getJdbcConnectionAccess().obtainConnection();
            Connection conn = null;
            String stmt = "SELECT status from insight";
            PreparedStatement ps = conn.prepareStatement(stmt);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
               boolean value = rs.getBoolean(status);   // returning false, i want this to return true as already set true in 2nd method and called saveAndFlush 
        }
    } catch (SQLException ex) {
    } finally {
        JdbcUtility.closeResources(conn, ps, rs);
    }
}

InsightRepository 正在扩展JpaRepository

@Repository
public interface InsightRepository extends JpaRepository<Insight, Long> {}
  

我想在方法3中更新状态的更新值(布尔值为true - 在方法2中更新)。   怎么做到这一点?

更新

我搜索了很多,并且不认为如果方法使用@Transactional进行注释,那么您可以在完成JPA事务之前提交更改。因此,如果要控制JPA事务,解决方案是删除@Transactional注释并使用entityManager.getTransaction()。

2 个答案:

答案 0 :(得分:0)

如果您想控制交易,请不要使用@Transactional

em; //entityManager

Transaction tx=em.getTransaction();
try{
   tx.begin();
   //do work
   tx.commit(); // comminted transaction 
 // start another transaction if you need to, doo more work etc.
...
}

这是使用JPA进行原子操作的最基本和最基本的代码块。

此外,没有必要unwrap实体经理,使用纯JPA。通过展开,您将当前实现绑定到JPA提供程序,这与JPA从底层JPA实现提供程序的独立性概念相反。换句话说,如果出于某种原因,Spring会将其JPA实现从Hibrnate更改为例如,它将停止工作。的EclipseLink。

答案 1 :(得分:0)

使用与第二种方法不同的bean中的@Transactional(propagation = Propagation.REQUIRES_NEW)注释创建一个方法(第四种方法)进行更新,并将第二种方法更改为调用第四种方法,如下所示:

@Component //or Service etc..
public class AnotherBean{

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void doUpdateWork(Request request){
    Insight insight = insightRepository.findOne(request.getTypeId());
    insight.setStatus(true);
    insightRepository.save(insight);
  }
} 

    @Override
    public ApiResponse doRestOfWork(Request request) {
        anotherBean.doUpdateWork(request);
        processOperation();    // calling 3rd method
    }