gpt4 book ai didi

java - @ElementCollection 不会分离

转载 作者:行者123 更新时间:2023-12-02 10:27:06 29 4
gpt4 key购买 nike

我的目标是克隆实体“产品”及其所有过滤器。

例如,我有一个实体(为简单起见,省略了 getter 和 setter):

@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ElementCollection()
private List<Filter> filters = new ArrayList<Filter>();
}

和可嵌入类:

@Embeddable
public class Filter {
@Column(length = 255, nullable = false)
private String name;
@Column(nullable = false)
private long variant = -1;
}

现在,如果我这样做:

entityManager.detach(product);
product.setId(null);
productService.save(product);

我将获得产品实体的副本,但带有原始产品的过滤器。与此同时,原始产品最终将根本没有过滤器..

这就是过滤器的表格行的样子:

之前:

product_id; name; variant
217; "f2"; 86

之后:

product_id; name; variant
218; "f2"; 86

我尝试从列表中分离每个过滤器,但它给了我错误。

如何让它复制带有实体的过滤器?

编辑:添加了完整的产品和过滤器代码:

package com.serhiy1.model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.*;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.SortableField;
import org.joda.time.DateTime;

import com.serhiy1.constraint.LocalePacker;

@Indexed
@Entity
@EntityListeners(ProductListener.class)
public class Product {
public static final int PRICE_PER_ONE = 0;
public static final int PRICE_PER_METER = 1;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private Long code;

private String name = "";

private String grouping = "";

@Field
@Column(columnDefinition="text")
private String title = "";

@Field
@Column(columnDefinition="text")
private String intro = "";

@Column(columnDefinition="text")
private String content = "";

@Field
@Column(columnDefinition="text")
private String contentHtml = "";

private String locale = "en";

private Long parentId = 0L;

private DateTime time;

private DateTime timeMod;

private Long balanceRequired = 0L;

private Integer index = 0;

@Field(name = "price_sort")
@SortableField(forField = "price_sort")
private Double price = 0.0;

private Integer pricePer;

@Transient
private long childrenCount = 0;
@Transient
private String image = "";
@Transient
private List<String> images = new ArrayList<String>();

@ManyToOne(targetEntity = User.class)
@JoinColumn(nullable = false, name = "user_id")
@LazyCollection(LazyCollectionOption.FALSE)
private User user;

@ManyToOne(targetEntity = Product.class)
@JoinColumn(nullable = true, name = "category_id")
@LazyCollection(LazyCollectionOption.FALSE)
private Product category;

@ElementCollection()
private List<Filter> filters = new ArrayList<Filter>();

@ElementCollection()
private List<Modifier> modifiers = new ArrayList<Modifier>();

public Product() {
}

@Transient
private String _title = "";
@Transient
private String _intro = "";
@Transient
private String _content = "";
@Transient
private String _contentHtml = "";

public void pack(String locale, List<String> locales) {
if(locale.contains("_")) return;
title = LocalePacker.repack(locale, _title, title, locales);
intro = LocalePacker.repack(locale, _intro, intro, locales);
content = LocalePacker.repack(locale, _content, content, locales);
contentHtml = LocalePacker.repack(locale, _contentHtml, contentHtml, locales);
}
public void unpack(String locale) {
_title = LocalePacker.unpackStr(locale, title).getOrDefault(locale, "");
_intro = LocalePacker.unpackStr(locale, intro).getOrDefault(locale, "");
_content = LocalePacker.unpackStr(locale, content).getOrDefault(locale, "");
_contentHtml = LocalePacker.unpackStr(locale, contentHtml).getOrDefault(locale, "");
}
public void copy(String landFrom, String landTo) {
title = LocalePacker.copyLang(title, landFrom, landTo);
intro = LocalePacker.copyLang(intro, landFrom, landTo);
content = LocalePacker.copyLang(content, landFrom, landTo);
contentHtml = LocalePacker.copyLang(contentHtml, landFrom, landTo);
}

public Modifier getModifier(String name) {
for(Modifier m: modifiers) {
if(m.getName().equals(name)) return m;
}
return null;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public long getCode() {
return code == null ? id : code;
}

public void setCode(long code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getGrouping() {
return grouping;
}

public void setGrouping(String grouping) {
this.grouping = grouping;
}

public String getTitle() {
return _title;
}

public void setTitle(String title) {
this._title = title;
}

public String getIntro() {
return _intro;
}

public void setIntro(String intro) {
this._intro = intro;
}

public String getContent() {
return _content;
}

public void setContent(String content) {
this._content = content;
}

public String getContentHtml() {
return _contentHtml;
}

public void setContentHtml(String contentHtml) {
this._contentHtml = contentHtml;
}

public String getLocale() {
return locale;
}

public void setLocale(String locale) {
this.locale = locale;
}

public long getParentId() {
return parentId;
}

public void setParentId(long parentId) {
this.parentId = parentId;
}

public DateTime getTime() {
return time;
}

public void setTime(DateTime time) {
this.time = time;
}

public DateTime getTimeMod() {
return timeMod;
}

public void setTimeMod(DateTime timeMod) {
this.timeMod = timeMod;
}

public long getBalanceRequired() {
return balanceRequired == null ? 0L : balanceRequired;
}
public void setBalanceRequired(long balanceRequired) {
this.balanceRequired = balanceRequired;
}

public Integer getIndex() {
//return index == null ? 1000 : index;
return index;
}
public void setIndex(Integer index) {
this.index = index;
}

public double getPrice() {
return price == null ? 0.0 : price;
}
public void setPrice(double price) {
this.price = price;
}

public int getPricePer() {
return pricePer == null ? PRICE_PER_METER : pricePer;
}
public void setPricePer(int pricePer) {
this.pricePer = pricePer;
}

public long getChildrenCount() {
return childrenCount;
}
public void setChildrenCount(long childrenCount) {
this.childrenCount = childrenCount;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public Product getCategory() {
return category;
}

public void setCategory(Product category) {
this.category = category;
}

public List<Filter> getFilters() {
return filters;
}

public void setFilters(List<Filter> filters) {
this.filters = filters;
}

public List<Modifier> getModifiers() {
return modifiers;
}

public void setModifiers(List<Modifier> modifiers) {
this.modifiers = modifiers;
}

public boolean isCategory() { return price < 0; }

@Override
public String toString() {
return "Article{" +
"id=" + id +
'}';
}
}

..

package com.serhiy1.model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Transient;

@Embeddable
public class Filter {
@Column(length = 255, nullable = false)
private String name;
@Column(nullable = false)
private long variant = -1;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getVariant() {
return variant;
}
public void setVariant(long variant) {
this.variant = variant;
}
}

最佳答案

我做了一个迷你项目试图复制您的问题。

这是一个带有 H2 数据库和 JPA(Hibernate 实现)的 String Boot 项目。

启动时,Hibernate 创建 2 个表:

create table product (
id bigint not null,
primary key (id)
)

create table product_filters (
product_id bigint not null,
name varchar(255) not null,
variant bigint not null
)

在创建过滤器的产品上,两个表都会插入:

insert 
into
product
(id)
values
(1)

insert 
into
product_filters
(product_id, name, variant)
values
(1, "f1", 1)

之后:

entityManager.detach(product);
product.setId(null);
productService.save(product);

hibernate 问题:

delete 
from
product_filters
where
product_id=1

这是正常的,因为 filters 是一个 ElementCollection,因此它完全由实体 Product 拥有。在 productService.save(product) 上,Hibernate 检测到 filters 集合已绑定(bind)到另一个 Product,因此删除旧绑定(bind)(从 product_filter 表),然后再创建新表。

解决删除问题的唯一方法是重新创建集合:

    List<Filter> filters = new ArrayList<Filter>(); 
filters.addAll(oldFilters);
product.setFilters(filters);

总而言之,解决方案如下:

// To trigger the fetch
List<Filter> filters = new ArrayList<Filter>(product.getFilters());
entityManager.detach(product);
product.setId(null);
product.setFilters(filters);
productService.save(product);

关于java - @ElementCollection 不会分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53867675/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com