需要将第一个对象的字段复制到第二个对象中

时间:2013-09-24 05:21:10

标签: java hibernate

我正在尝试从数据库中删除记录,但在删除它之前,我将其中一个子项复制到另一个记录中,这会导致以下错误。

SEVERE: org.hibernate.StaleStateException: Batch update returned unexpected row count 
from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:59)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3224)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3126)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3456)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:364)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:356)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:278)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:328)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
.....

1)在第一个函数中(从记录18中获取列表并添加到新记录中)

 ....
 User user = (User) session.get(User.class, 18L);
 tx.commit();

 User client = new User();
 client.getmyList().setItems(user.getmyList().getItems());
 return client;

2)在第二个功能中(删除记录18)

 User user = (User) session.get(User.class, 18L);
 session.delete(user);

3)在第三个功能中(保存新记录)

 session.save(client);             

用户类

@Entity
@DynamicUpdate
public class User{

    .....

    @OneToOne(cascade = CascadeType.ALL)
    public UnitWatchList getmyList() {
        return myList;
    } 

    ...
} 

3 个答案:

答案 0 :(得分:1)

session.delete(user);之后,您是否在第二个功能中关闭了交易?也许您的问题出在session.delete()而非session.save()

如何在items中映射UnitWatchList

此致

答案 1 :(得分:1)

我可能只是写一个DAO方法deleteAndMoveChildrensTo(Long victimId,Long recipientId),像这样:

DAO课程:

public boolean deleteAndMoveChildrensTo(Long victimId, Long recipientId) {
        User victim = (User) getSession().load(User.class, victimId);
        User recipient = (User) getSession().load(User.class, recipientId);
        for (UnitWatchList unitWatch : victim.getmyList().getItems()) {
            unitWatch.setUser(recipient);
        }
        recipient.getmyList().addAll(victim.getmyList().getItems());
        getSession().saveOrUpdate(recipient);
        getSession().flush();
        getSession().evict(victim);
        victim = (User) getSession().load(User.class, victimId);
        getSession().delete(victim);
        return true;
    }

和相应的Service类如下

服务类。

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public boolean deleteAndMoveChildrensTo(Long victimId, Long recipientId) {
    DAO.deleteAndMoveChildrensTo(victimId, recipientId);
}

试试这个希望这会解决你的问题...

答案 2 :(得分:1)

Hibernate有一个默认的第一级缓存,它与会话对象相关联。因此,一旦对对象的访问将被缓存,将从缓存中获取进一步的访问。

其次,将引用对象分配给其他变量只会更改引用。

让我们跟踪您的代码

  1. 您检索一个User对象,让它在内存位置(a)User user = (User) session.get(User.class, 18L)
  2. 中说出来
  3. 用户对象被分配给另一个对象。请注意,它仅设置为内存位置。没有实际的副本。 client.getmyList().setItems(user.getmyList().getItems());
  4. 再次移除对象。但是,检索到的对象仍然在内存位置(a),因为它是从缓存User user = (User) session.get(User.class, 18L);中提取的
  5. 删除位于内存位置的对象(a)session.delete(user);
  6. 尝试保存一个对象,该对象也涉及位于内存位置的用户对象(a)session.save(client);但是,没有实际对象。哪个被删除。
  7. 原型模式通常用于应对对象。克隆方法也可以被覆盖。但是,一旦创建了实体对象的副本。 hibernate会话不会维护新对象,这是另一个问题。

    根据我的拙见,删除一个物品如果再次保存则不是一个好习惯。如果你想保存,为什么要删除?还应重新安排映射以解决这些问题。

    另见

    Prototype Pattern

    Hibernate Caching

    Types, Values, and Variables