【问题标题】:Hibernate: illegally attempted to associate a proxy with two open SessionsHibernate:非法尝试将代理与两个打开的会话相关联
【发布时间】:2013-01-08 09:37:02
【问题描述】:

我有两种方法:

public static Ticket issueTicket(User user,Service service,String[] seats) {
    Session ticSess= DB.factory.openSession();
    ticSess.beginTransaction();
    Date d= new Date();
    Ticket ticket=new Ticket(d, service, user);

    ticSess.save(ticket);
    ticSess.getTransaction().commit();
    int seatCount=seats.length;
    for (int i=0;i<seatCount;i++){
        int seatID=Integer.parseInt(seats[i]);
        Seat seat=getSeatByID(seatID);
        seat.setTicket(ticket);
        ticSess.update(seat);
    }
    return ticket;


}

和,

public static Seat getSeatByID(int seatID) {
    Session proSess = DB.factory.openSession();
    proSess.beginTransaction();
    Seat c = (Seat) (proSess.load(Seat.class, seatID));
    proSess.getTransaction().commit();

    return c;
}

当我调用 issueTicket 方法时,我得到:

illegally attempted to associate a proxy with two open Sessions

如果我在 getSeatByID 方法中关闭会话,则会出现另一个错误,告知会话已关闭。这是堆栈跟踪:

at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at ir.ac.shirazu.cse.Terminal.Seat_$$_javassist_9.setTicket(Seat_$$_javassist_9.java)
at ir.ac.shirazu.cse.Database.DB.issueTicket(DB.java:231)

【问题讨论】:

  • 添加堆栈跟踪后,离开getSeatByID() 后似乎发生了一些延迟初始化。只需在一个会话中完成所有操作即可正常工作

标签: java eclipse hibernate tomcat


【解决方案1】:

在返回之前尝试在getSeatByID() 中关闭proSess。目前Seat 确实仍然附加到在getSeatByID() 中打开的会话。

【讨论】:

  • 如果我在 getSeatByID 方法中关闭会话,将会有另一个错误提示会话已关闭。
  • @Pishist 你能发送“关闭会话”异常的完整堆栈跟踪吗?也许在某个时候会发生一些延迟初始化?另一件事是,我不完全理解您为什么在单独的会话和事务中加载 Seat。您似乎打开了“每个数据库操作的事务”,这基本上是一种反模式。
  • 我想如果我在同一个会话中加载 Seat,问题就会得到解决。谢谢。我应该做什么而不是每个数据库操作的事务?我听说交易在我们关闭它们之前不会影响数据库...
  • @Pishist 在此处了解工作单元:docs.jboss.org/hibernate/orm/3.3/reference/en/html/…
【解决方案2】:

我遇到了同样的问题。但是在使用单例模式进行会话之后,我就完成了。我正在使用 Hibernate 4.2.x。

这是我的会话类,用于获取数据库事务等的会话。

public class SessionClass {

static Session session = PoolManager.getSession();

public static Session getSession() {
    if (session != null || session.isOpen()) {
        return session;
    } else {
        session = PoolManager.getSession();
        return session;
    }
}

}

我正在使用的 Hibernate Helper 类。

public class PoolManager {
private static final SessionFactory sessionFactory;
private static final ServiceRegistry serviceRegistry;

static {
    try {
        // Create the SessionFactory from standard (hibernate.cfg.xml) 
        // config file.
        Configuration configuration = new Configuration();
        configuration.configure();

        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    } catch (Throwable ex) {
        // Log the exception. 
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static Session getSession() {
    return sessionFactory.openSession();
}

}

【讨论】:

  • 那你怎么处理并发呢?
【解决方案3】:

我在尝试从 Envers 会话关联实体时遇到了这个问题。

通过在将其冒泡到我的算法之前“刷新”所述实体(通过 PK 获取在我的非 Envers 会话中检索它)来修复该问题。

【讨论】:

    【解决方案4】:

    使用session.opensession().get(.....).. 代替session.opensession().load(.....)

    【讨论】:

      【解决方案5】:

      如果您在提交 proSess 之前执行 proSess.evict(c) 会怎样?

      【讨论】:

        猜你喜欢
        • 2015-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        相关资源
        最近更新 更多