[英]Handling Hibernate Transactions
目前我在每个 Controller方法中都复制了这些代码:
Transaction transaction = HibernateUtil.getSessionFactory().getCurrentSession().getTransaction();
if (!HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().isActive()) {
transaction.begin();
}
这是正确的方法,还是有更好的方法,也许在我可以参考的单独的课程中? 如果是这样,怎么样? 每当我试图将它放在一个单独的类中并从其他类引用它时,它就失败了。
编辑 :我正在尝试使用尽可能少的外部库。 如果Java在JDK中内置了ORM / JPA实现,我就不会使用Hibernate
我自己多次碰到这个。 通常我的第一个建议是Spring事务管理 ,但是我知道你试图限制你正在使用的第三方库的数量。
由于您在HibernateUtil类中使用静态API,您可能会发现在方法中合并逻辑并在回调中放置“您想要在事务中执行的操作”代码(这会将控制器变为控制器)会很有帮助。
首先,定义一个接口来描述每个控制器的inTransaction行为:
public interface TransactionCallback {
void doInTransaction();
}
现在,在HibernateUtil类中创建一个静态方法来处理开始,提交,并在必要时回滚您的事务:
public class HibernateUtil {
public static void inTransaction(TransactionCallback tc) {
Transaction transaction = HibernateUtil.getSessionFactory().getCurrentSession().getTransaction();
if (!HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().isActive()) {
transaction.begin();
try {
tc.doInTransaction();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
}
}
在你的控制器中,你将使用一个匿名内部类的新方法:
....
HibernateUtil.inTransaction(new TransactionCallback() {
void doInTransaction() {
// do stuff for this controller
}
});
....
这种方法至少应该处理你想要消除的重复,并且有足够的空间来扩展它以处理特定的异常等。
您必须在每次事务后关闭hibernate事务(例如,Controller请求)。 在这种情况下,您将不需要
if (!HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().isActive())
每次请求后你都需要调用.close()。
最好使用以下代码:
class Controller {
//...
commonActionMethod() {
begin transaction
specificActionMethod();
close transaction
}
这个Controller类的子节点应该实现specificActionMethod()。
代码很干净。 交易是安全的。 不需要第三方库。
这样,您不需要依赖JDK以外的任何库。 你可以通过注释来关闭或开启交易。
如果你开始管理实例(服务),你可以结合使用FactoryPattern + JDK Proxies(实际接口)+ AOP Concepts来制作很多魔法。
您可以创建单独的连接类。
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
@SuppressWarnings("deprecation")
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from Annotation
return new AnnotationConfiguration().configure().buildSessionFactory();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
在服务器端,您可以写: -
Session session=null;
Transaction tx=null;
try {
session =HibernateUtil.getSessionFactory().openSession();
tx=session.beginTransaction();
} catch (HibernateException e) {
e.printStackTrace();
}finally
{
session.close();
}
如果您在项目中使用spring。 我建议使用弹簧AOP使用TX,因为您只需指定事务的切入点。 Spring AOP TX将根据您的切入点开始并提交事务,并且还可以在发生异常时回滚TX。 请仔细阅读示例链接 - 这里
package com.project.stackoverflow;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class HibernateUtil {
private static final ThreadLocal threadSession = new ThreadLocal();
private static SessionFactory sessionFactory;
/**
* A public method to get the Session.
*
* @return Session
*/
public static Session getSession() {
Session session = (Session) threadSession.get();
// Open a Session, if this thread has none yet
if ((null == session) || !session.isOpen()) {
logger.info("Null Session");
session = sessionFactory.openSession();
logger.info("Session Opened");
threadSession.set(session);
}
return session;
}
public static void closeSession() {
Session session = (Session) threadSession.get();
// Open a Session, if this thread has none yet
if (null != session) {
session.close();
session = null;
threadSession.set(null);
}
}
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
logger.info("Inside set session Factory");
this.sessionFactory = sessionFactory;
logger.info("After set session Factory");
}
public static void save(Object obj) {
getSession().save(obj);
getSession().flush();
}
public static void saveOrUpdate(Object obj) {
getSession().saveOrUpdate(obj);
getSession().flush();
}
public static void batchUpdate(Object obj) {
getSession().saveOrUpdate(obj);
getSession().flush();
}
public static void update(Object obj) {
getSession().update(obj);
getSession().flush();
}
public static void delete(Object obj) {
getSession().delete(obj);
getSession().flush();
}
}
您可以选择此解决方案。 我为Hibernate实例化和使用创建了一个单独的JavaClass。 你可以从这里获得会议,这可能满足你的需要。 希望能帮助到你 :)
我用过这种技术。
我的Servlet上下文是这样的:
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="configLocation">
<beans:value>classpath:hibernate.cfg.xml</beans:value>
</beans:property>
<beans:property name="configurationClass">
<beans:value>org.hibernate.cfg.AnnotationConfiguration</beans:value>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">${jdbc.dialect}</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager" />
然后你可以简单地使用
@Autowired
private SessionFactory sessionFactory;
每当我想使用会话或进行任何操作时,我只需这样做:
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(userAccount);
transaction.commit();
session.close();
我认为这会有所帮助。
如果您有像glassfish这样的应用程序服务器,它已经嵌入了eclipselink JPA / ORM实现,您可以使用标准JEE注释来管理事务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.