一起使用Spring和EJB事务

时间:2018-03-27 11:10:57

标签: spring spring-boot jpa transactions ejb-3.0

我在尝试将实体添加到数据库时收到错误。我提到了this。但它没有太多关于我的问题的信息

我有一个EJB jar,用于管理get,save和update实体。

这是我的远程ejb

@Remote
public abstract interface DatalayerService{
   public abstract void add(Object object)
}

这是实现

@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class DatalayerServiceImpl implements DatalayerService{
  @PersistenceContext(name="myPersistenceUnit")
   EntityManager em = null;

  @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void add(Object object) throws FatalException{
        try {
            em.persist(object);
        }
        catch (Throwable e){
            throw manageDatalayerError(e);
        }
        finally {

        }
    }
}

我正在尝试在我的应用程序中使用上面的ejb

1)

@ComponentScan({"com.springboot"})
@EnableJpaRepositories
@SpringBootApplication
public class SpringEjbApplication extends SpringBootServletInitializer{


    public static void main(String args[]){
        SpringApplication.run(SpringApplication.class,args);
    }



    @Bean
    public DatalayerService datalayerService() throws NamingException{
        return new DatalayerServiceImpl();
    }


    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException{
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[]{"com.springboot.pojo"});
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        em.setJpaVendorAdapter(vendorAdapter);
        em.setPersistenceUnitName("myPersistenceUnit");
        em.setJpaProperties(additionalProperties());
        return em;
    }



    @Bean
    public DataSource dataSource() throws NamingException{
        return (DataSource) new JndiTemplate().lookup("openejb:Resource/MyDataSource");
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }


    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }


    private Properties additionalProperties(){
        Properties properties = new Properties();
        properties.setProperty("hibernate.max_fetch_depth", "3");
        properties.setProperty("hibernate.default_batch_fetch_size", "2");
        properties.setProperty("hibernate.jdbc.batch_size", "100");
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.format_sql", "false");
        return properties;
    }
}

2)休息服务

@RestController
public class HomeEndPoint{

    @Autowired
    private IUserService iUserService;

    @GetMapping("/createUser")
    @Transactional(rollbackFor = {ServiceExpectedException.class,FatalException.class,MandatoryParameterMissingFatalException.class})
    public void createUser() throws FatalException,ServiceExpectedException{
        iUserService.createUser();
    }

}

3)用户服务及其impl

public interface IUserService{
   public void createUser() throws FatalException;
}

    @Service
@Transactional(rollbackFor = {ServiceExpectedException.class,FatalException.class,MandatoryParameterMissingFatalException.class})
public class UserServiceImpl implements IUserService{
     @Autowired
    private DatalayerGenericService datalayerGenericService;

     @Override
    public void createUser() throws FatalException,ServiceExpectedException{
     Team team = new Team(simpleContextService);
        team.setGroupName("MyTeam");
        team.setStoreId(100);
        // Team
        datalayerGenericService.add(team);
        Log.info(this,"add team ");
        // Build user1
        datalayerGenericService.add(user1);
        Log.info(this,"############################# Added User1 ######################################");
        // Build user2
        datalayerGenericService.add(user2);
        Log.info(this,"############################# Added User2 ######################################");

}
}

我尝试使用网址

运行其余服务
http://localhost:6180/SpringBootDatalayer/createUser

我收到以下异常。

  

INFO:(com.edifixio.springboot.service.impl.UserServiceImpl)

     ####################### teamOid 20 INFO:(com.edifixio.springboot.service.impl.UserServiceImpl)      #######################添加了User1 ######################### ############ INFO :( com.edifixio.springboot.service.impl.UserServiceImpl)      #######################添加了User2 ######################### ############ INFO:http-nio-6180-exec-1:AbstractBatchImpl.release:HHH000010:批量发布后仍然      

包含JDBC语句2018-03-27 16:28:17,683:错误:   http-nio-6180-exec-1:BatchingBatch.performExecution:HHH000315:   执行批处理的异常[java.sql.BatchUpdateException:批量输入   0插入TEAM(CREATE_TIMESTAMP,PROJECT_GROUP_NAME,   LAST_UPDATE_TIMESTAMP,STORE_ID,ID)值('2018-3-27   16:28:17.447000 +5:30:0','MMA_TEST','2018-3-27 16:28:17.503000   +5:30:0',100,21)中止。调用getNextException以查看原因。],SQL:插入TEAM(CREATE_TIMESTAMP,PROJECT_GROUP_NAME,   LAST_UPDATE_TIMESTAMP,STORE_ID,ID)值(?,?,?,?,?)

从异常中可以看出,正在使用datalayerGenericService创建team,user1和user2。但是尝试再次执行以给出AbstractBatchImpl.release:HHH000010:在批量发布时它仍然包含JDBC语句。

以下是我得到的例外情况:

  

java.sql.BatchUpdateException:批处理条目1插入TEAM   (CREATE_TIMESTAMP,PROJECT_GROUP_NAME,LAST_UPDATE_TIMESTAMP,   STORE_ID,ID)值('2018-3-29 12:9:26.611000 +5:30:0','MMA_TEST',   '2018-3-29 12:9:26.836000 +5:30:0',100,23)被中止。呼叫   getNextException查看原因。

如何解决此问题?为什么查询执行两次?

如果EJB方法中发生任何异常,它应该回滚事务。但它没有发生

注意:如果我从服务中删除@Transactional注释,它可以正常工作。 我正在使用TomEE 7.0.2服务器。

2 个答案:

答案 0 :(得分:0)

我是如何解决此问题的?

我被误解为此处涉及EJB内容 但是@M。 Deinum澄清说,这里没有涉及EJB,不管我是否添加了这些注释,这意味着我的DatalayerServiceImpl只是一个SpringBean。 添加所有这些接口和注释并没有给我任何东西,只是增加了Spring中默认忽略的代码的复杂性和开销(除了Spring之类的支持)。

来到我的问题我已经宣布Team In Users类

@ManyToOne(cascade={CascadeType.PERSIST},fetch=FetchType.LAZY)
@JoinColumn(name="TEAM_ID",nullable=false)
@JsonBackReference
private Team team;

创建用户时,我将Created团队实例引用到Users类

我在做

Team team = new Team(simpleContextService);
team.setGroupName("MMA_TEST");
team.setStoreId(100);
// Team
Long teamOid = datalayerGenericService.updateWithId(team);

Users user1 = new Users(simpleContextService);
...Set other fields
user1.setTeam(team);

由于团队声称Cascade type在用户内部持续存在,因此在持久保存用户时尝试插入团队。

所以我已将Cascade type更改为MERGE。所以它工作正常。

答案 1 :(得分:0)

从技术上讲,您既不插入用户也不插入团队。您将它们持久化为PersistenceContext。代码离开时

virtualenv

只要您根据需要标记它,就必须提交或刷新或关闭会话。它在第一次插入(团队)时失败,因为你没有上面列出的任何内容。

是的 - 您正在使用EJB注释。事实上,你使用Hibernate,只有@Transactional,因为Spring服务注释在这里有效。