13

我正在尝试将 pojo 添加到另一个 pojo 的集合中。我确定我在某个地方犯了一个非常愚蠢的错误,但我不知道如何解决它。

我有一个包含列列表的 pojo LookupTable:

public class LookupTable {
  private long id;
  // More properties go here...
  private List<Column> columns;

  public void addColumn(Column column) {
    this.columns.add(column);
  }

  // More methods go here...
}

在我的休眠配置中,我有:

<class name="LookupTable" table="ARR_LOOKUP_TABLE">
  <id name="id" column="ID">
    <generator class="native"/>
  </id>
  <!-- Some properties here -->
  <bag name="columns" cascade="all,delete-orphan" access="field">
    <key column="LOOKUP_TABLE" not-null="true"/>
    <one-to-many class="Column"/>
  </bag>
</class>

<class name="Column" table="ARR_LOOKUP_COLUMN">
  <id name="id" column="ID">
    <generator class="native"/>
  </id>
  <!-- Some properties here -->
</class>

在我的 Spring 配置文件中,我有:

<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="*" propagation="REQUIRED"/>
  </tx:attributes>
</tx:advice>
<aop:config>
  <aop:pointcut id="managers" expression="execution(public * com.foo.*Manager.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="managers"/>
</aop:config>

最后是我的管理器类(com.foo.LookupTableManager)中所有失败的代码:

public void addColumnToTable(Column column, long tableId) {
  LookupTable lookupTable = this.lookupTableDao.findById(tableId);
  lookupTable.addColumn(column);
  this.lookupTableDao.saveOrUpdate(lookupTable);
}

这里的变量lookupTableDao 是指一个简单的DAO 类,它扩展了HibernateDaoSupport。

我得到的错误是:

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
  at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
  at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
  at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
  at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
  at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
  at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
  at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
  at com.foo.AbstractDao.saveOrUpdate(AbstractDao.java:29)
  at com.foo.LookupTableManager.addColumnToTable(LookupTableManager.java:338)
... etc ...

好的,我了解我收到的基本信息。但我不明白的是我在哪里获得第二次会议......有人可以帮助我吗?

我正在使用 Hibernate 3.2.6.ga、Spring 2.5.5 和 Tomcat 6.0

4

7 回答 7

5

结果我根本没有交易。我在其他配置文件之一中使用了几乎相同的事务配置。

那边的切入点也被称为“经理”,所以我的顾问在这里引用了另一个文件中的切入点。

重命名切入点解决了我的问题。

于 2008-10-21T08:40:44.370 回答
3

我的猜测是lookupTableDao.findById调用在一个会话中获取您的对象,但这lookupTableDao.saveOrUpdate是一个不同的会话 - 您如何Session通过 Spring 获取对象?

Column对象来自哪里- 已经在数据库上还是新的?

于 2008-10-21T08:00:46.790 回答
2

问题在于 Open Session In 视图过滤器映射。它在 getSession 和其他保存时创建了一个会话。

您只能将 singleSession 更改为 false 默认为 true

于 2010-07-16T16:58:13.273 回答
2

显然使用合并可能会解决问题

myInstance = (myInstanceClass) Session.merge(myInstance);
于 2011-10-09T15:17:24.230 回答
2

我的以下代码遇到了同样的问题:我想更新某个实体商店。我从这个方法中检索它:

@Override
public Store getStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Store>() {
        @Override
        public StoredoInHibernate(Session session) throws HibernateException, SQLException {
            return (Store) session.createCriteria(Store.class)
                    .add(Restrictions.eq(Store.PROP_ID, storeId))
                    .uniqueResult();
        }
    });
}

然后,我用以下方法更新商店:

@Override
public void updateStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Void>() {
        @Override
        public Void doInHibernate(Session session) throws HibernateException, SQLException {
            Store toBeUpdated =  getStoreByStoreId(storeId);

            if (toBeUpdated != null){
                // ..change values for certain fields
                session.update(toBeUpdated);
            }
            return null;
        }
    });
} 

事实证明,我收到了“非法尝试...”错误,因为 get 方法的第一个会话没有关闭,而我试图用另一个会话更新商店。我的解决方案是在更新方法中移动检索要更新的商店的调用。

@Override
public void updateStoreByStoreId(final long storeId) {
    getHibernateTemplate().execute(new HibernateCallback<Void>() {
        @Override
        public Void doInHibernate(Session session) throws HibernateException, SQLException {
            Store toBeUpdated =  (Store) session.createCriteria(Store.class)
                    .add(Restrictions.eq(Store.PROP_ID, storeId))
                    .uniqueResult();

            if (toBeUpdated != null){
                // ..change values for certain fields
                session.update(toBeUpdated );
            }
            return null;
        }
    });
} 
于 2012-04-09T09:13:52.377 回答
0

如果您只想对部分代码进行事务处理,则可以使用以下内容:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

在课堂上:

@Autowired private SessionFactory sessionFactory;

稍后,围绕应该在同一事务中执行操作的代码:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Stuff stuff = getStuff();
manipulate(stuff);
send(stuff);
save(stuff);

tx.commit();

我在一些长时间运行的批处理作业的循环中使用它。

于 2011-11-10T20:55:15.573 回答
0

我使用的是 Windows 服务器 IIS,只是将 AppPool Managed Pipeline 模式从 Integrated 更改为 Classic 解决了我的问题。

谢谢

于 2017-09-22T22:14:27.300 回答