在我们的项目中,我们试图获取当前部署在使用Liberty的WebSphere上的代码。
MDB收到消息后,会在服务中调用将数据插入DB2数据库中的方法。
问题在于调用flush时,我们在日志中收到以下错误:
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1136) ~[hibernate-entitymanager-5.1.3.Final.jar:5.1.3.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1297) ~[hibernate-entitymanager-5.1.3.Final.jar:5.1.3.Final]
[ERROR ] WLTC0017E: Resources rolled back due to setRollbackOnly() being called.
没有其他错误,例如SQL查询不正确或类似错误。
由于此代码在WebSphere中可以正常工作,所以我想知道配置是否有问题或Liberty在处理事务方面是否有不同之处。
以下是相关的代码和配置:
@Service
public class IdentificationService implements IIdentificationService {
@Autowired
private IIdentificationDAO identificationDAO;
@Transactional
public Identification insertIdentificationData(RequestForIdentificationRequest request, String referenceNumber) {
final Identification identification = new Identification();
...
identificationDAO.create(identification);
LOGGER.debug("Identification record saved with id: {}", identification.getId());
return identification;
}
}
@Repository
public class IdentificationDAO extends BaseDAO implements IIdentificationDAO {
@Override
public void create(final Identification identification) {
insertRecord(identification);
}
}
public abstract class BaseDAO
{
@PersistenceContext(name = "UserData", unitName = "UserData")
private EntityManager em;
/**
* @param record
*/
public <T> void insertRecord(final T record)
{
em.persist(record);
em.flush();
}
}
public class Identification implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(sequenceName = "IDENTIFICATION_SEQ", name = "sequenceGenerator", allocationSize = 1)
private Long id;
...
}
applicationContext.xml
<jee:jndi-lookup id="userDataSource" jndi-name="jdbc/userdataDB" />
<bean id="userDataEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="UserData" />
<property name="persistenceXmlLocation" value="classpath:persistence-userdata.xml" />
<property name="dataSource" ref="userDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.DB2Dialect" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userDataEntityManagerFactory" />
</bean>
server.xml
<library id="DB2JCCLib">
<fileset dir="/etc/liberty/jdbc" includes="db2jcc4.jar, db2jcc_license_cisuz.jar, db2jcc_license_cu.jar"/>
</library>
<dataSource id="UserDB" jndiName="jdbc/userdataDB" type="javax.sql.XADataSource"
isolationLevel="TRANSACTION_READ_COMMITTED">
<jdbcDriver libraryRef="DB2JCCLib" javax.sql.XADataSource="com.ibm.db2.jcc.DB2XADataSource"/>
<properties.db2.jcc serverName="${datasource.userdb.serverName}" portNumber="${datasource.userdb.portNumber}"
databaseName="${datasource.userdb.databaseName}"
user="user" password="password"/>
</dataSource>
更新:问题原来是配置中指向多个数据库的多个事务管理器bean(命名相同)。 给它们赋予唯一的名称并在Transactional注释中显式引用它们可以达到目的