0

我说的是 T5,Java 1.7。

我找不到任何关于在 Tapestry 服务中使用休眠的足够详细的教程。我需要的是创建可以独立处理休眠的 Tapestry 服务。例如,这可能是调度程序服务。该服务将处理数据库中的一些对象及其状态,并在应用程序后台工作。

问题是,如何正确地将它与 Hibernate 绑定?应该注入哪个 Hibernate 对象以便在该服务中进一步工作?


目前的做法是在这个服务内部注入一个HibernateSessionSource对象(通过服务的构造函数传递它的实例),然后手动创建会话,开始事务等等。例如:

public synchronized void deleteJob(long id) {
    Session session = hss.create();
    JobItem job = (JobItem) session.get(JobItem.class, id);
    if (job != null) {
        Transaction tx = session.beginTransaction();
        try {
            session.delete(job);
            tx.commit();
        } catch (HibernateException e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}

它看起来很丑,不像Tapestry的风格。什么是聪明的方法?

4

3 回答 3

2

如果您正在处理非 Tapestry 托管服务,则可以使用HibernateSessionManager 。

try {
   do_stuff(hibernateSessionManager.getSession());
   hibernateSessionManager.commit();
}catch(Exception ex){
   hibernateSessionManager.abort();
}

对于挂毯托管服务和页面/组件,您可以阅读详细文档。这里有几个链接

  1. http://tapestry.apache.org/using-tapestry-with-hibernate.html
  2. http://tapestry.apache.org/hibernate-user-guide.html
于 2013-03-21T15:01:37.873 回答
2

这个问题由两部分组成:

如何在 Tapestry 托管服务中使用休眠?

您可以使用@Inject注释在您的服务中注入休眠会话:

@Inject
private Session session;

或作为构造函数参数:

public MyService buildMyService(Session session) {
  return new MyAwsomeService(session);
}

然后你可以在服务中使用它。此会话由 Tapestry 作为 perthread 服务进行管理。它将在首次使用时打开,并在请求结束后关闭。

如何在 Tapestry 托管服务中使用休眠转换?

您可以使用注入的HibernateSessionManager手动执行此操作:

@Inject
private HibernateSessionManager manager;

public void doSomeWork(Entity entity) {
  try {
    session.delete(entity);
    manager.commit();
  } catch (Exception e) {
    manager.abort();
  }
}

或者您可以使用HibernateTransactionAdvisor注释所有事务方法@CommitAfter为服务提供建议

public interface MyService {

  @CommitAfter
  void doSomeWork(Entity entity);

}

public class MyTapestryModule {
  @Match("*Service")
  public void adviseTransactions(HibernateTransactionAdvisor advisor,
                                 MethodAdviceReceiver receiver) {
    advisor.addTransactionCommitAdvice(receiver);
  }
}

或者你可以使用HibernateTransactionDecorator装饰服务

public class MyTapestryModule {
  @Match("*Service")
  public <T> T decorateTransactions(Class<T> serviceInterface,
                                    T delegate,
                                    String serviceId,
                                    HibernateTransactionDecorator decorator) {
    return decorator.build(serviceInterface, delegate, serviceId);
  }
}

这个怎么运作。它将在方法调用之前启动新事务并在之后尝试提交。如果在方法调用期间发生任何错误,该事务将被回滚。

于 2013-03-22T11:39:13.553 回答
1

您可以直接@Inject Session 而不是 HibernateSessionManager。

Session Tapestry 提供的实际上是一个每个线程的延迟加载代理。底层会话由 Tapestry 管理,并在每次请求后由 PerThreadManager 清理。

这几乎是魔术!

于 2013-03-21T22:38:35.053 回答