【问题标题】:cannot update an object with jpa无法使用 jpa 更新对象
【发布时间】:2014-08-25 14:37:22
【问题描述】:

我在更新记录时遇到问题:

package legacy.database;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public class Queries {

    private static final Logger log = Logger.getLogger(Queries.class.getName());
    private final EntityManagerFactory emf = Persistence.createEntityManagerFactory("LegacyDatabasePU");
    private final EntityManager em = emf.createEntityManager();

    public Queries() {
    }

    private List<Clients> findAll() {
        Query q = em.createQuery("select c from Clients c");
        List<Clients> clients = q.getResultList();
        return clients;
    }




    public Clients findById(int id) {
        Clients client = em.find(Clients.class, id);
        return client;
    }


    public void update(Clients c2) {
        Clients c1 = em.find(Clients.class, c2.getId());
        java.util.Date date = new java.util.Date();
        Timestamp t = new Timestamp(date.getTime());
        c2.setDateUpdated(t.toString());
        em.getTransaction().begin();
        c2.setDateUpdated(t.toString());
        c1 = c2;
        log.info(c1.getNotes());
        log.info(c2.getNotes());
        em.getTransaction().commit();
    }
}

分配 c1=c2 有问题吗?我是否必须手动通过 c1 并更新每条记录?

【问题讨论】:

  • 未找到任何使用EntityManager 的更新数据库操作,如em.merge() !!!
  • @WundwinBorn:修改附加实体不需要合并。
  • @JBNizet 是的,当然merge() op 不需要托管实例,但我的意思是 OP 帖子中的分离实例。

标签: java jpa variable-assignment equals jpql


【解决方案1】:

在事务中执行 find(),然后在事务中调用您的变异方法。然后提交将自动更新对象。只需简单地移动 begin txn 即可。只有您知道各种更新是什么,因此不会尝试清理它

try
{
    em.getTransaction().begin();

    Clients c1 = em.find(Clients.class, c2.getId());
    Timestamp t = new Timestamp(new java.util.Date().getTime());
    c2.setDateUpdated(t.toString());
    c1 = c2;
    log.info(c1.getNotes()); log.info(c2.getNotes());

    em.getTransaction().commit();
}
finally
{
    if (em.getTransaction().isActive())
    {
        em.getTransaction().rollback();
    }
}

【讨论】:

  • 您应该在答案中添加一个代码示例。并且请修改 update 方法,让它接受一个 ID 作为参数:这样会更清楚。
  • 如何结合删除和创建来模拟更新?使用persist时,也许指定被持久化对象的id?
【解决方案2】:

如果实体没有在EntityManager注册,可能像你的c2,那么它不会被更新,除非你使用em.persistem.merge等等。

c1 = c2 只是将c1 引用指向c2 引用。

从下面的评论中,您要做的是将c2的属性复制到c1,可以这样做

  • 借助能够进行列模式编辑的编辑器(IntelliJ、Eclipse、jEdit 等)静态调用每个 setter/getter
  • 使用像Apache BeanUtils这样的库;这将使用反射。

在这两种情况下,您都必须记住:

  • 如果应该这样做,请进行深层复制;例如:如果有OneToMany,您可能应该复制子实体。
  • 不要复制不应复制的字段(如唯一约束)

【讨论】:

  • 这是我关心的问题——我想从字面上复制对象本身。
  • 然后看看EntityManager.merge。或者使用 org.springframework.beans.BeanUtils.copyProperties(Object, Object) 之类的东西或任何类似的东西。
  • 好的,我没有使用 spring,但 copyProperties 听起来和我想要的完全一样。
猜你喜欢
  • 1970-01-01
  • 2020-02-08
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多