Решения? Autocomit ложные
<property name="hibernate.connection.autocommit" value="false"/>
Существует одна большая проблема с этим вы должны явно сказать о каждой реализации, когда совершить пример дао ручной фиксации реализации:
public void commit() throws Exception {
Session session = getEntityManager().unwrap(Session.class);
Transaction tx = session.getTransaction();
if (tx.isActive()) {
session.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
connection.commit();
}
});
}
}
Использование этого:
@TransactionAttribute(TransactionAttributeType.MANDATORY)
private Voucher save(Voucher entity, Boolean isCreate) throws Exception {
voucherPoolService.save(entity);
List<VoucherTag> tags = _detachTags(entity);
List<VoucherCaption> captions = _detachCaptions(entity);
if (isCreate) {
voucherDAO.save(entity);
} else {
voucherDAO.merge(entity);
}
retailerService.updateTime(entity);
_clearCollections(entity);
_attachTags(entity, tags);
_attachCaptions(entity, captions);
voucherDAO.merge(entity);
// you have to explicitly say when to commit
getDao().commit();
return entity;
}
Вы бы спросили себя, почему я не ставил его в общую реализацию dao? Но вы попадете в ту же ситуацию, что и режим автокомитов, и вы этого не сделаете.
К счастью, у меня есть красивое решение с использованием Hibernate перехватчики, который будет обрабатывать, что без явного определения A:
getDao().commit();
Вот единица настойчивости пример вашего упорства.XML:
<persistence-unit name="webservices" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>Your entitys here</class>
<class>Your entitys here</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.use_outer_join" value="true"/>
<property name="hibernate.connection.provider_class"
value="com.zaxxer.hikari.hibernate.HikariConnectionProvider"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.autoReconnect" value="true"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
<property name="hibernate.ejb.use_class_enhancer" value="true"/>
<property name="hibernate.ejb.interceptor"
value="webservices.dao.transaction.TransactionInterceptor"/>
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.multi_tenant_connection_provider"
value="webservices.multitenancy.HikariTenantConnectionProvider"/>
<property name="hibernate.tenant_identifier_resolver"
value="webservices.multitenancy.ThreadLocalIdentifierResolver"/>
<property name="hibernate.current_session_context_class" value="thread"/>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
<property name="hibernate.transaction.auto_close_session" value="true"/>
<property name="hibernate.hikari.maximumPoolSize" value="30"/>
<property name="hibernate.hikari.connectionTestQuery" value="SELECT 1"/>
<property name="hibernate.hikari.leakDetectionThreshold" value="10000"/>
<property name="jboss.entity.manager.factory.jndi.name" value="webservicesEMF"/>
<property name="jboss.entity.manager.jndi.name" value="webservicesEM"/>
<property name="hibernate.hikari.idleTimeout" value="300000"/>
<property name="hibernate.hikari.transactionIsolation" value="TRANSACTION_SERIALIZABLE"/>
</properties>
Generic даосские части:
@Stateless
public class GenericDAO<E, ID extends Serializable> extends GenericDAOImpl<E, ID> {
private Class<E> entityClass;
private Class<ID> idClass;
protected static Logger log = LogManager.getLogger(GenericDAO.class);
@PersistenceContext(name = "webservices")
protected EntityManager em;
private static final JPASearchProcessor searchProcessor = new JPASearchProcessor(new JPAAnnotationMetadataUtil());
public GenericDAO() {
super();
entityClass = (Class<E>) DAOUtil.getTypeArguments(GenericDAOImpl.class, this.getClass()).get(0);
init();
}
@PostConstruct
protected void initialize() {
setEntityManager(em);
setSearchProcessor(searchProcessor);
}
DAORegistry части:
@Stateless
public class DAORegistry {
public static EntityManager getEntityManager() {
EntityManager em = null;
try {
InitialContext ic = new InitialContext();
em = (EntityManager) ic.lookup("webservicesEM");
} catch (NamingException e) {
e.printStackTrace();
}
return em;
}
И МАГИЯ Уловка:
Нанести перехватчик:
<property name="hibernate.ejb.interceptor" value="webservices.dao.transaction.TransactionInterceptor"/>
И ваша реализация перехватчик:
public class TransactionInterceptor extends EmptyInterceptor {
@Override
public void beforeTransactionCompletion(Transaction noTx) {
DAORegistry.getEntityManager().unwrap(Session.class);
Transaction tx = session.getTransaction();
if (tx.isActive() && !tx.wasRolledBack() && !tx.wasCommitted()){
session.doWork(Connection::commit);
}
}
Теперь Вам не нужно больше ручной фиксации реализации:
getDao().commit();
Ваш код дао будет работать в любом месте, как ожидается, с хорошей реализации JTA CMT , Код ниже будет работать как шарм:
@TransactionAttribute(TransactionAttributeType.MANDATORY)
private Voucher save(Voucher entity, Boolean isCreate) throws Exception {
voucherPoolService.save(entity);
List<VoucherTag> tags = _detachTags(entity);
List<VoucherCaption> captions = _detachCaptions(entity);
if (isCreate) {
voucherDAO.save(entity);
} else {
voucherDAO.merge(entity);
}
retailerService.updateTime(entity);
_clearCollections(entity);
_attachTags(entity, tags);
_attachCaptions(entity, captions);
voucherDAO.merge(entity);
return entity;
}
Для более недель я искал какой-то пример, который предоставит мне такую хорошую реализацию и я не мог найти его, поэтому я хочу поделиться своим Усвоением.
Теперь вы можете использовать свой стандарт EJB3, как вы ожидали, он должен работать,
Оставьте мне свои комментарии и Усвоение ниже. :)