org.hibernate.Session更新方法失效,求助排查原因及事务关联问题
Hibernate Session的update/merge/saveOrUpdate无更新且无异常问题排查
使用org.hibernate.Session的update、merge、saveOrUpdate方法时,数据库未发生更新,且无任何异常抛出。
问题代码(update方法)
@Override public void update(Domain domain) { // 创建SessionFactory SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); // 获取Session Session session = sessionFactory.openSession(); // 此处返回false boolean contains = session.contains((LogItem)domain); // 尝试过以下所有方法,均无效 //session.update((LogItem)domain); //session.update( ((LogItem)domain).getClass().getName(), (LogItem)domain ); //session.merge( (LogItem)domain ); //session.merge( ((LogItem)domain).getClass().getName(), (LogItem)domain ); //session.saveOrUpdate( (LogItem)domain ); session.saveOrUpdate( ((LogItem)domain).getClass().getName(), (LogItem)domain ); // 关闭Session session.close(); }
正常工作的save和read方法
create方法
public Serializable create(Domain domain) throws NamingException, SQLException { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); session.save(domain); session.close(); return domain; }
read方法
public Domain read(long id) { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); LogItem logItem = session.get( LogItem.class, id ); session.close(); return logItem; }
Hibernate配置文件(hibernate.cfg.xml)
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库连接配置 --> <property name="hibernate.connection.datasource">jdbc/CRUDS_MySQL_Data_Source</property> <!-- JDBC连接池大小 --> <property name="connection.pool_size">1</property> <!-- SQL方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 打印SQL语句 --> <property name="hibernate.show_sql">true</property> <!-- 启用JTA集成 --> <property name="hibernate.transaction.jta.platform"> org.hibernate.engine.transaction.jta.platform.internal.WebLogicJtaPlatform </property> <!-- 实体映射文件 --> <mapping resource="com/mycompany/cruds/domain/LogItem.hbm.xml"/> </session-factory> </hibernate-configuration>
Hibernate依赖信息
[INFO] com.mycompany.cruds:app:ear:1.0.2-SNAPSHOT [INFO] +- com.mycompany.cruds:server:ejb:1.0.2-SNAPSHOT:compile [INFO] | +- org.hibernate:hibernate-core:jar:5.4.23.Final:compile [INFO] | | +- org.jboss.logging:jboss-logging:jar:3.4.1.Final:compile [INFO] | | +- javax.persistence:javax.persistence-api:jar:2.2:compile [INFO] | | +- org.javassist:javassist:jar:3.24.0-GA:compile [INFO] | | +- net.bytebuddy:byte-buddy:jar:1.10.17:compile [INFO] | | +- antlr:antlr:jar:2.7.7:compile [INFO] | | +- org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:jar:1.1.1.Final:compile [INFO] | | +- org.jboss:jandex:jar:2.1.3.Final:compile [INFO] | | +- com.fasterxml:classmate:jar:1.5.1:compile [INFO] | | +- javax.activation:javax.activation-api:jar:1.2.0:compile [INFO] | | +- org.dom4j:dom4j:jar:2.1.3:compile [INFO] | | +- org.hibernate.common:hibernate-commons-annotations:jar:5.1.2.Final:compile [INFO] | | +- javax.xml.bind:jaxb-api:jar:2.3.1:compile [INFO] | | \- org.glassfish.jaxb:jaxb-runtime:jar:2.3.1:compile [INFO] | | +- org.glassfish.jaxb:txw2:jar:2.3.1:compile [INFO] | | +- com.sun.istack:istack-commons-runtime:jar:3.0.7:compile [INFO] | | +- org.jvnet.staxex:stax-ex:jar:1.8:compile [INFO] | | \- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.15:compile [INFO] | \- com.mycompany.cruds:interface:jar:1.0.2-SNAPSHOT:compile [INFO] | \- com.mycompany.cruds:domain:jar:1.0.2-SNAPSHOT:compile [INFO] | \- mysql:mysql-connector-java:jar:5.1.6:compile [INFO] +- com.mycompany.cruds:facade:war:1.0.2-SNAPSHOT:compile [INFO] \- com.mycompany.cruds:web-client:war:1.0.2-SNAPSHOT:compile
HibernateUtil工具类
public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // 从hibernate.cfg.xml创建SessionFactory return new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } public static void shutdown() { // 关闭缓存和连接池 getSessionFactory().close(); } }
可正常工作的EntityManager实现
@PersistenceContext(unitName = "your_persistence_unit_name") private EntityManager em; public void update(Domain domain) { em.merge(domain); }
补充:调用链与容器事务配置
DomainHibernateDaoBean(包含所有CRUD方法)
public class DomainHibernateDaoBean { public Serializable create(Domain domain) throws Exception { ... } public Domain read(long id) throws Exception { ... } public void update(Domain domain) throws Exception { ... } }
CrudsTransactionSessionBean(容器管理事务)
import javax.ejb.SessionContext; @Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class CrudsTransactionSessionBean implements CrudSessionLocal { private DomainHibernateDaoBean domainHibernateDaoBean = new DomainHibernateDaoBean(); private boolean throwException; @Resource private SessionContext sessionContext; public CrudsTransactionSessionBean() { super(); } @Override @TransactionAttribute(TransactionAttributeType.REQUIRED) public void update(Domain domain) throws Exception { try { domainHibernateDaoBean.update(domain); if (throwException) { throw new Exception("Mockup exception"); } } catch (Exception e) { sessionContext.setRollbackOnly(); throw e; } } @Override @TransactionAttribute(TransactionAttributeType.REQUIRED) public Serializable create(Domain domain) throws Exception { try { Serializable serializableTemp = domainHibernateDaoBean.create(domain); if (throwException) { throw new Exception("Mockup exception"); } return serializableTemp; } catch (Exception e) { sessionContext.setRollbackOnly(); throw e; } } @Override public Domain read(long id) throws Exception { try { Domain searchResult = domainHibernateDaoBean.read(id); if (throwException) { throw new Exception("Mockup exception"); } return searchResult; } catch (Exception e) { sessionContext.setRollbackOnly(); throw e; } } }
persistence.xml配置
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="your_persistence_unit_name" transaction-type="JTA"> <jta-data-source>jdbc/CRUDS_MySQL_Data_Source</jta-data-source> <class>com.mycompany.cruds.domain.LogItem</class> <class>com.mycompany.cruds.domain.Domain</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
疑问与诉求
原本认为容器事务与HibernateUtil获取的事务是同一事务,但现在对此存疑。设置throwException=true时,create操作会被回滚,这让我疑惑:sessionContext.setRollbackOnly()是否会回滚HibernateUtil的事务?恳请帮忙排查Session更新失效的原因,以及容器事务与Hibernate事务的关联问题。
内容的提问来源于stack exchange,提问作者user2902165
相关产品推荐
相关产品推荐

