麻烦与Hibernate单程协会 [英] Trouble with Hibernate One Way Associations

查看:119
本文介绍了麻烦与Hibernate单程协会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现在Java应用程序中的Hibernate持久层,我遇到一些麻烦吧。我遇到我每次试图访问一个简单的,单向的关联时间没有代理错误。我没有很正确的方式实现休眠 - 我使用的会话线程控制方法,他们不建议你不要在生产中使用。然而,它们使用它在其教程。我仍然想获得基本的工作,所以我想下面的教程就可以了。但是,我不能让简单的协会工作。我有一个类,它看起来是这样的:

I'm trying to implement a Hibernate persistence layer in a Java application and I'm having some trouble with it. I'm encountering a no proxy error every time I attempt to access a simple, one way association. I haven't implemented Hibernate in quite the right way - I am using the thread method of Session control, which they do suggest you don't use for production. However, they use it in their tutorials. I am still trying to get the basics working, so I figured following the tutorials would be fine. However, I can't get the simple association to work. I have a class that looks something like this:

public class Foo {
    private Long id;
    private String name;
    private Bar bar;

    // Static Handler Methods - I'll flesh these out further down in the question.
    public static List getAllFoo();


    // Convenience methods
    public String getBarName() {
        return bar.getName();
    }

    // Accessor methods
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Bar getBar() {
        return bar;
    }

    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

Foo的酒吧类被实现为简单的单向关联。它在像这样的.hbm.xml:

Foo's Bar class is implemented as a simple one-way association. It's in the .hbm.xml like so:

<many-to-one name="bar" column="bar_id" not-null="true" />

我创建了美孚在里面foo的静态方法,像这样:

I create the Foo's in a static method inside Foo like so:

public static List getAllFoo() {
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction t = session.beginTransaction();
    List foos = session.createCriteria(Foo.class).list();
    t.commit();
    return foos;
}

在休眠实例配置为使用1连接池,并使用线程方法会话处理,像这样:

The hibernate instance is configured to use a connection pool of 1 and uses the threading method for session handling like so:

<property name="connection.pool_size">1</property>
<property name="current_session_context_class">thread</property>

我每次我试图访问创建的对象之一,使用 getBarName()功能的关联时遇到异常。这是一个错误的代理,它看起来像这样:

I'm encountering a exception every time I try to access the association using the getBarName() function on one of the created objects. It's a proxy error, it looks like this:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at Bar_$$_javassist_7.getName(Bar_$$_javassist_7.java)
    at Foo.getBarName(Bar.java:126)

因此​​,为了使长话短说,这就是我开始和错误我第一次遇到。从那时起,我花了好几天读的Hibernate文档和帖子在这里,试图找出如何使这项工作。

So to make a long story short, this is what I started with and the error I first encountered. Since then I've spent the last several days reading the Hibernate docs and posts here to try and figure out how to make this work.

我学到的东西 - 我认为 - 是Hibernate的对象需要连接到一个会话。即,会话它们被创建。当我创建我的对象,在 getAllFoo()那就是这些对象涉及到会话。在该次会议的律师代理存在并有道理。然而,当我打电话 t.commit() - 因为我使用的会话线程处理方法 - 我结束了会议。这样做的结果是,当我去打电话 bar.getName()后,酒吧现在是一个孤立的代理。这是代理谁的会话已经关闭。

What I've learned - I think - is that Hibernate objects need to be connected to a Session. Namely, the Session they are created by. When I am creating my objects, in getAllFoo() that is the Session that those objects relate to. In that session the Bar proxy exists and makes sense. However, when I call t.commit() - because I am using the Thread method of Session handling - I am ending that Session. The result of this is that when I go to call bar.getName() later, bar is now an orphaned proxy. It is a proxy who's session has been closed.

我发现了两个可能的解决方案:

I found two possible solutions:

1)不要关闭初始会话。离开它开放不是通过调用 t.commit() getAllFoo()

1) don't close the initial session. Leave it open by not calling t.commit() in getAllFoo().

这工作 - 但是,我不认为我可以使用它。我将有成千上万的一次加载这些对象。他们将需要而用户思考时间,以保持打开的时间过长 - 但我需要能够自由访问关联。并有可能在未来,会并发问题与数据库锁。

This worked - however, I don't think I can use it. I'm going to have thousands of these objects loaded at once. They are going to need to stay open for an extended period of time while the user has think time - but I need to be able to access the associations freely. And there may, in the future, be concurrency issues with database locks.

2)重新连接对象到一个新的Session呼吁关联之前。

2) reattach the object to a new Session before calling on the association.

这没有奏效。也许我没有错 - 我找到的文档不清晰。我试图启动一个新的会话和呼叫 session.load(这一点,this.id)之前,我访问的关联。像这样的:

This didn't work. Maybe I did it wrong - the documentation I found isn't clear. I attempted to start a new session and call session.load(this, this.id) before I accessed the association. Like this:

public Bar getBar() {
    Bar tmp = null;
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction t = session.beginTransaction();
    session.load(this, this.id);
    tmp = bar;
    t.commit();
    return tmp;
}

然后我修改 getBarName()调用 getBar(),而不是访问吧。这就产生了一个新的错误:

I then modified getBarName() to call getBar() instead of accessing bar. This resulted in a new error:

org.hibernate.PersistentObjectException: attempted to load into an instance that was already associated with the session: [Foo#1]

我阅读教程,职位和Hibernate文档我仍然不能满脑子都在这个结构天后估计连。因此,我要求计算器来阐明这一些轻。

I guess even after days of reading tutorials, posts and the hibernate documentation I still can't wrap my head around this structure. So I ask StackOverflow to shed some light on this.

首先,如果你可以计算出来,所发生的事情在code我现在有?与会话打开或关闭?为什么它在第一种方法中的代理错误,但如权利要求所述会话仍然打开,对象仍连接在第二λ

First, if you can figure it out, what's happening in the code I currently have? Is the session opened or closed? Why does it have a proxy error in the first method, but claim the session is still opened and the object still attached in the second?

二,什么是处理会话的正确方法? - 我怎么竟使这项工作我想,我想用的方式是每个请求会话 - 这似乎是最流行的和适用于我的情况。但后来如何,实际上与各协会和懒加载执行?

Second, what is the correct way to handle Sessions - how do I actually make this work? The way I think I want to use is session per request - that seems to be the most popular and applicable to my situation. But then how is that actually implemented with associations and lazy loading?

是的,我知道我不应该使用线程的方法 - 但我有一个整体的其他批次的相关JTA VS主题的问题VS管理这个问题是已经太久

Yes, I know I shouldn't be using the thread method - but I have a whole other batch of questions related to JTA vs Thread vs Managed and this question is already too long.

推荐答案

我相信Hibernate的默认延迟初始化。所以,当你装在会话FOOS名单,没有与其相关的酒吧被加载到任何企图使用它们。到那个时候,你已经关闭会话,从而导致错误。

I believe Hibernate defaults to lazy initialization. So while you loaded the list of Foos in the session, none of their associated Bars are loaded until any attempts to use them. By that time, you've already closed the session, which results in the error.

一些可能的解决方案:


  • 启用渴望获取对美孚,律师协会

  • 连接上获取(有效的预先抓取)

  • 尝试访问会话内的酒吧(这会工作,但你打电话Foo.getBar()只是为了让关联Bar对象加载)

从评论更新:

成语会话/交易管理:

Session sess = factory.openSession();
Transaction tx;
  try {
    tx = sess.beginTransaction();
    //do some work
    ...
    tx.commit();
  }
  catch (Exception e) {
    if (tx!=null) tx.rollback();
      throw e;
  }
  finally {
    sess.close();
  }

要重新安装超然的对象(基于<一个href=\"http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-detached\"相对=nofollow>引用文档):

To reattach the "detached" objects (based on reference docs):

如果对象已被修改:更新新的会话对象。

if object has been modified: update the object in new session

// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher layer of the application
cat.setMate(potentialMate);

// later, in a new session
secondSession.update(cat);  // update cat
secondSession.update(mate); // update mate

如果对象是未经修改的,可以使用锁():

if object is unmodified, can use lock():

//just reassociate:
sess.lock(fritz, LockMode.NONE);
//do a version check, then reassociate:
sess.lock(izi, LockMode.READ);
//do a version check, using SELECT ... FOR UPDATE, then reassociate:
sess.lock(pk, LockMode.UPGRADE);

这篇关于麻烦与Hibernate单程协会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆