不确定如何正确更新持久化的JPA实体

huangapple go评论97阅读模式
英文:

Not sure how to properly update persistent JPA entities

问题

让我们假设我有一个包含产品实体列表的类别实体,这些产品属于该类别:

Category c = new Category(/*包含类别属性的一些JSON*/);

使用此CategoryManager持久化类别实体:

// 导入

@RequestScoped
public class CategoryManager {
    @PersistenceContext
    private EntityManager em;

    public CategoryManager() {}

    @Transactional
    public void save(Category c) {
        em.persist(c);
    }

    public Category find(long id) {
        return em.find(Category.class, id);
    }

    // 其他方法
}

现在有一个函数应该创建一个新的产品实体,并将其添加到特定类别的产品列表中:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addProduct(ProductDTO product) {
    Category category = categoryManager.find(product.getCategory().getId());

    if (category == null)
        return Response.status(Response.Status.NOT_FOUND).entity("Category not found.").build();

    Product new_product = new Product(product);
    productManager.save(new_product);
    category.getProducts().add(new_product);
    // categoryManager.save(category);

    return Response.ok(new_product).build();
}

这似乎可以正确更新数据库,但是当我尝试列出类别时,其产品列表在JSON中为空:

{
    "id": 1,
    "name": "Bread",
    "products": []
}

只有在我重新启动我的Open Liberty服务器之后,它才会正确列出产品:

{
    "id": 1,
    "name": "Bread",
    "products": [
        {
            "id": 2,
            "name": "Wholegrain"
        }
    ]
}

我怀疑这是因为我在将产品附加到其产品列表后未保存该类别,但是当我取消注释我发布的代码中的注释行时,它会抱怨重复的键值。

英文:

Let's say I have a Category entity that contains a list of Product entities which fall under that category:

Category c = new Category(/*some JSON with category attributes*/);

The Category entity is persisted using this CategoryManager:

// imports

@RequestScoped
public class CategoryManager {
    @PersistenceContext
    private EntityManager em;

    public CategoryManager() {}

    @Transactional
    public void save(Category c) {
        em.persist(c);
    }

    public Category find(long id) {
        return em.find(Category.class, id);
    }

    // other methods
}

Now there's a function that is supposed to create a new Product entity and add it into the list of products of a certain category:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addProduct(ProductDTO product) {
    Category category = categoryManager.find(product.getCategory().getId());

    if (category == null)
        return Response.status(Response.Status.NOT_FOUND).entity("Category not found.").build();

    Product new_product = new Product(product);
    productManager.save(new_product);
    category.getProducts().add(new_product);
    // categoryManager.save(category);

    return Response.ok(new_product).build();
}

This seems to update the database correctly, but when I try to list the category, its list of products appears empty in JSON:

{
    "id": 1,
    "name": "Bread",
    "products": []
}

Only after I restart my Open Liberty server does it actually list the products correctly:

{
    "id": 1,
    "name": "Bread",
    "products": [
        {
            "id": 2,
            "name": "Wholegrain"
        }
    ]
}

I suspect it's because I don't save the category after appending the product to its list of products, but when I uncomment the commented out line in the code I posted, it complains about duplicate key values.

答案1

得分: 1

所以我最终通过向我的CategoryManager添加以下内容来解决这个问题:

@Transactional
public Category update(Category c) {
    return em.merge(c);
}

并且更新addProduct()方法如下:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addProduct(ProductDTO product) {
    Category category = categoryManager.find(product.getCategory().getId());

    if (category == null)
        return Response.status(Response.Status.NOT_FOUND).entity("Category not found.").build();

    Product new_product = new Product(product);
    productManager.save(new_product);
    category.getProducts().add(new_product);
    categoryManager.update(category); // <---- the changed line

    return Response.ok(new_product).build();
}

看起来问题已经解决了,但我愿意听取建议和更好的解决方案。

英文:

So I ended up fixing this by adding the following to my CategoryManager:

@Transactional
public Category update(Category c) {
    return em.merge(c);
}

And updating the addProduct() method like this:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addProduct(ProductDTO product) {
    Category category = categoryManager.find(product.getCategory().getId());

    if (category == null)
        return Response.status(Response.Status.NOT_FOUND).entity("Category not found.").build();

    Product new_product = new Product(product);
    productManager.save(new_product);
    category.getProducts().add(new_product);
    categoryManager.update(category); // <---- the changed line

    return Response.ok(new_product).build();
}

It seems to have fixed the issue, but I'm open to suggestions and better solutions.

huangapple
  • 本文由 发表于 2023年4月17日 03:32:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定