我想在Glassfish 3.1.2应用服务器上使用带有EclipseLink的JTA(容器管理事务)将JPA实体持久化到MySQL数据库。但是,这根本不起作用。 EclipseLink日志显示SELECT查询正确执行,并且序列也更新。但是在调用persist()
后没有执行INSERT查询。
EclipseLink日志记录:
persist() operation called on: my.package.name.MyEntity@d39a7b6.
TX beginTransaction, status=NO_TRANSACTION
TX Internally starting
external transaction has begun internally
Connection acquired from connection pool [default].
Execute query DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + #PREALLOC_SIZE WHERE SEQ_NAME = #SEQ_NAME")
reconnecting to external connection pool
UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [50, SEQ_GEN]|#]
Execute query ValueReadQuery(name="SEQUENCE" sql="SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = #SEQ_NAME")
SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
bind => [SEQ_GEN]
local sequencing preallocation for SEQ_GEN: objects: 50 , first: 14.501, last: 14.550
Connection released to connection pool [default].
TX commitTransaction, status=STATUS_ACTIVE
TX Internally committing
所以我可以在MySQL数据库中看到序列更新,但与MyEntity
关联的表仍然是空的。
这是我的实体类:
@Entity
@Table(name = "my_entity")
public class MyEntity implements Serializable, Cloneable {
@Id
@GeneratedValue
protected long id;
// (..) more fields
}
我正在使用基于Java的Spring Configuration关于EntityManager,如下所示:
@Configuration
public class EntityManagerConfiguration {
@Bean
public EntityManagerFactory entities() throws Exception {
LocalContainerEntityManagerFactoryBean theEntityManager = new LocalContainerEntityManagerFactoryBean();
theEntityManager.setPackagesToScan(MyEntity.class.getPackage().getName());
theEntityManager.setJtaDataSource(dataSource());
theEntityManager.setPersistenceUnitName("entities");
theEntityManager.setJpaVendorAdapter(jpaVendorAdapter());
theEntityManager.setJpaProperties(jpaProperties());
theEntityManager.afterPropertiesSet();
return theEntityManager.getNativeEntityManagerFactory();
}
@Bean
public Properties jpaProperties() {
Properties props = new Properties();
props.setProperty("eclipselink.ddl-generation", "create-tables");
props.setProperty("eclipselink.weaving", "false");
props.setProperty("eclipselink.logging.level", "FINEST");
props.setProperty("eclipselink.logging.parameters", "true");
props.setProperty("eclipselink.target-server", "SunAS9");
return props;
}
@Bean
public DataSource dataSource() throws Exception {
return (DataSource) JNDIUtils.getLocalJNDIResource("jdbc/entitiesDB");
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
EclipseLinkJpaVendorAdapter theVendorAdapter = new EclipseLinkJpaVendorAdapter();
theVendorAdapter.setDatabase(Database.MYSQL);
return theVendorAdapter;
}
@Bean
public PlatformTransactionManager platformTransactionManager(){
return new JtaTransactionManager();
}
}
请注意persistence.xml
is not needed any more when using the setPackagesToScan()
method。
最后,调用persist()
方法的代码:
@Repository
public class EntityRepository {
@PersistenceContext(unitName = "entities")
private EntityManager entityManager;
public void persist(MyEntity myEntity) {
entityManager.persist(myEntity);
}
}
我在SO上已经阅读了很多类似的问题,但是它们似乎都没有足够精确地反映我的问题以便能够解决它。我在这里缺少什么?
答案 0 :(得分:2)
好吧,我设法解决了这个问题。正如遗嘱指出的那样,我需要在@Transactional
方法上使用persist()
属性。此外,我需要将@EnableTransactionManagement
注释添加到我的EntityManagerConfiguration
类。 This Spring blog给了我这个主意。
要完成此回答,我列出了以下EntityManagerConfiguration
和EntityRepository
类的最终版本:
@Configuration
@EnableTransactionManagement
public class EntityManagerConfiguration {
// class content did not change
}
@Repository
public class EntityRepository {
@PersistenceContext(unitName = "entities")
private EntityManager entityManager;
@Transactional
public void persist(MyEntity myEntity) {
entityManager.persist(myEntity);
}
}
现在我的实体很乐意插入,我可以去周末庆祝! (好吧,事实上几个小时)