【问题标题】:insert/update an entity that has a many to many relationship with another entity using java criteria api使用java标准api插入/更新与另一个实体具有多对多关系的实体
【发布时间】:2015-05-04 12:36:02
【问题描述】:

正如问题所说。我有两个表 Productscategories
产品表

...
create table products (
  id int primary key generated always as identity(start with 100, increment by 1),
  name varchar(30),
  quantity int,
  unit_cost decimal not null,
  brand_name varchar(30)
)
...  

类别表

...
create table categories
(
  name varchar(30) primary key,
  description varchar(30),
  date_created date,
)

... 他们的关系是多对多的关系,所以我创建了一个关系表。

关系表

...
create table product_categories
(
  product_id int not null,
  category_name varchar(30) not null
)
alter table product_categories add constraint product_categoriesFK foreign key (product_id)
references products (id)
alter table product_categories add constraint category_productsFK foreign key (category_name)
references categories (name)  

这些都有各自的实体类。

产品实体

@Entity
@Table(name = "PRODUCTS")
public class Product implements Serializable {
     private static final long serialVersionUID = 1L;
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Basic(optional = false)
     @Column(name = "ID")
     private Integer id;
     @Size(max = 255)
     @Column(name = "NAME")
     private String name;
     @Column(name = "QUANTITY")
     private Integer quantity;
     @Column(name = "UNIT_COST")
     private Integer unitCost;
     @JoinTable(name = "REQUISITION_PRODUCTS", joinColumns = {
          @JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID")}, inverseJoinColumns = {
     @JoinColumn(name = "REQUISITION_ID", referencedColumnName = "ID")})
     @ManyToMany
     private Collection<Requisition> requisitionCollection;
     @ManyToMany(mappedBy = "productCollection", cascade = CascadeType.ALL)
     private Collection<Category> categoryCollection;
     @JoinColumn(name = "BRAND_NAME", referencedColumnName = "NAME")
     @ManyToOne
     private Brand brand;
     @JoinColumn(name = "DEAL_ID", referencedColumnName = "ID")
     @ManyToOne
     private Deal dealId;
     @OneToMany(mappedBy = "product")
     private Collection<Feature> featureCollection;
     ...

类别实体

@Entity
@Table(name = "CATEGORIES")
public class Category implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "NAME")
    private String name;
    @Column(name = "DATE_CREATED")
    @Temporal(TemporalType.DATE)
    private LocalDate dateCreated;
    @Size(max = 255)
    @Column(name = "DESCRIPTION")
    private String description;
    @JoinTable(name = "PRODUCT_CATEGORIES", joinColumns = {
    @JoinColumn(name = "CATEGORY_NAME", referencedColumnName = "NAME")}, inverseJoinColumns = {
    @JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID")})
    @ManyToMany
    private Collection<Product> productCollection;
    ...

这些实体类是使用 netbeans ide 生成的。未创建实体表的关系,因此我不知道如何插入/更新 产品 所属的 类别
这是我执行插入/更新的代码。

@Override
public int update(Object value, Product t) {
    CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
    CriteriaUpdate<Product> cu = cb.createCriteriaUpdate(Product.class);

    cu.set(Product_.brand, t.getBrand());
    cu.set(Product_.id, t.getId());
    cu.set(Product_.name, t.getName());
    cu.set(Product_.quantity, t.getQuantity());
    cu.set(Product_.unitCost, t.getUnitCost());

     // cu.set(Product_.categoryCollection, t.getCategoryCollection());

    Root<Product> root = cu.getRoot();
    Predicate tester = cb.equal(root.get(Product_.id), value);
    cu.where(tester);

    Query q = getEntityManager().createQuery(cu);
    return q.executeUpdate();
} 

产品元模型类

...
public class Product_ {
     public static volatile SingularAttribute<Product, Integer> quantity;
     public static volatile CollectionAttribute<Product, Requisition> requisitionCollection;
     public static volatile CollectionAttribute<Product, Category> categoryCollection;
     public static volatile SingularAttribute<Product, Deal> dealId;
     public static volatile SingularAttribute<Product, Integer> unitCost;
     public static volatile SingularAttribute<Product, String> name;
     public static volatile CollectionAttribute<Product, Feature> featureCollection;
     public static volatile SingularAttribute<Product, Integer> id;
     public static volatile SingularAttribute<Product, Brand>    brand;
     ...

据我所知,元模型类需要一个类别,而不是类别的集合。请有人告诉我如何解决这个问题。
软件
netbeans 8.0.2
glassfish 服务器 4.1
jdk1.8.0_40

【问题讨论】:

  • 你为什么使用CriteriaUpdate?既然您似乎正在更新单个产品,为什么不简单地 persist/merge 产品?
  • 成功了,感谢您的帮助。

标签: jpa criteria java-ee-7 metamodel


【解决方案1】:

当您拥有整条记录时,您不应使用CriteriaUpdate 进行简单的 id 更新。只需使用

getEntiyManager().merge(t);

【讨论】:

  • 我还需要向品牌中的所有产品插入交易,我认为这需要对品牌中的所有产品进行批量更新。既然合并更新了实体的记录,那么如何执行批量更新呢?
  • 这是一个完全不同的问题,我建议您搜索 JPA 更新/插入查询,如果您有问题,请返回 SO。
猜你喜欢
  • 2016-01-13
  • 2022-08-16
  • 2015-08-25
  • 2011-07-21
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多