SpringHibernate分离实体传递给持久化,级联问题

olhwl3o2  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(215)

我有一个关于保存相关实体的大问题。我需要保存多个elementaryflowbase对象:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class ElementaryFlowBase {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@EqualsAndHashCode.Include
private UUID id;

private String name;

@ManyToOne
@JoinColumn(name = "fk_elementary_flow_category", referencedColumnName = "id")
private ElementaryFlowCategory category;

@ManyToOne
@JoinColumn(name = "fk_elementary_flow_sub_category", referencedColumnName = "id")
private ElementaryFlowSubCategory subCategory;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@ManyToOne
@JoinColumn(name = "fk_uom", referencedColumnName = "id")
private UnitOfMeasure unitOfMeasure;

@OneToMany(mappedBy = "elementaryFlowBase", cascade = CascadeType.PERSIST)
private Set<BaseEnvironmentalImpact> coefficientFactors;

@EqualsAndHashCode.Include
private String originalId;
}

在它里面有不同的baseenvironmentalimpact(我使用cascade将它们从父母那里解救出来)。

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class BaseEnvironmentalImpact {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@EqualsAndHashCode.Include
private UUID id;
private double value;
private double normalizedValue;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = "fk_methodology", referencedColumnName = "id")
private Methodology methodology;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = "fk_impact_category", referencedColumnName = "id")
private ImpactCategory impactCategory;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = "fk_impact_indicator", referencedColumnName = "id")
private ImpactIndicator impactIndicator;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@EqualsAndHashCode.Include
private String originalId;

//ref
@ManyToOne
@JoinColumn(name = "fk_elementary_flow_base")
private ElementaryFlowBase elementaryFlowBase;

@ManyToOne
@JoinColumns({
        @JoinColumn(
                name = "process_base_id",
                referencedColumnName = "process_base_id"),
        @JoinColumn(
                name = "reference_product_id",
                referencedColumnName = "reference_product_id")
})
private ProcessTemplate processTemplate;
}

基本环境影响有方法论、影响类别、影响指标(这些实体也是相关的)。
方法:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Methodology {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@EqualsAndHashCode.Include
private UUID id;
private String name;
@OneToMany(mappedBy = "methodology", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<ImpactCategory> impactCategories;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@EqualsAndHashCode.Include
private String originalId;
}

影响类别:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class ImpactCategory {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@EqualsAndHashCode.Include
private UUID id;
private String name;
@OneToMany(mappedBy = "impactCategory", cascade = CascadeType.PERSIST)
private Set<ImpactIndicator> impactIndicators;

//ref
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "fk_methodology", referencedColumnName = "id")
private Methodology methodology;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@EqualsAndHashCode.Include
private String originalId;

}

碰撞指示器:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class ImpactIndicator {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@EqualsAndHashCode.Include
private UUID id;
private String name;
@ManyToOne
@JoinColumn(name = "fk_uom", referencedColumnName = "id")
private UnitOfMeasure unitOfMeasure;

//ref
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name= "fk_impact_category", referencedColumnName = "id")
private ImpactCategory impactCategory;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@EqualsAndHashCode.Include
private String originalId;

}

保存elementaryflowbase我想使用级联保存所有这些实体。
通过这些设置,我可以保存第一个元素FlowBase(使用Crudepository):

@GetMapping("/elementaryflowbases")
    public String importElementaryFlowBases() {
    System.out.println("Elementary flow bases import started");

    Set<ElementaryFlowBase> items =  importer.getElementaryFlowBases();

    for (ElementaryFlowBase item : items){
        elementaryFlowBaseRepository.save(item);
    }
    return "Elementary flow bases has been imported: + " + items.size() + "elements!";
}

但是在第二步,我有一个错误:

detached entity passed to persist: xxx.sp_model.sustainability.model.assessment.ImpactCategory

方法、影响类别、影响指标可能与某些基本环境影响相同。但是一些基本的环境影响可能有其他的方法,影响类别,影响指标。所以对于cascade,我想保存或更新(或者使用db上的内容,对我来说是一样的)。
怎么了?有什么建议吗?
先谢谢你
编辑saveall(不带for循环)解决问题。但这是一个测试,看看如何保存或更新数据库中已经存在的东西。为了更好地理解,我有另一个对象,称为processtemplate,它有其他baseenvironmentalimpact,但可以使用相同的方法、impactcategory和impactindicator:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class ProcessTemplate {
@EmbeddedId
@EqualsAndHashCode.Include
private ProcessTemplateId id;

@ManyToOne
@JoinColumn(name = "fk_process_base", referencedColumnName = "id")
private ProcessBase processBase;

@ManyToOne
@JoinColumn(name = "fk_reference_flow_base", referencedColumnName = "id")
private FlowBase referenceProduct;

@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(
        name="processtemplates_flowtemplates",
        joinColumns={
                @JoinColumn(name = "process_base_id", referencedColumnName = "process_base_id"),
                @JoinColumn(name = "reference_product_id", referencedColumnName = "reference_product_id")
        },
        inverseJoinColumns = @JoinColumn(name = "fk_flowtemplate", referencedColumnName = "id")
)
private Set<FlowTemplate> flowsTemplate;

@OneToMany(cascade = CascadeType.MERGE)
private Set<ElementaryFlowTemplate> elementaryFlowsTemplate;

@ManyToOne
@JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;

@Enumerated(EnumType.STRING)
private Validation validation;

@OneToMany(cascade = CascadeType.MERGE)
private Set<BaseEnvironmentalImpact> environmentalImpacts;

@EqualsAndHashCode.Include
private String originalId;

@PrePersist
void id() {
    this.id = new ProcessTemplateId(processBase.getId(), referenceProduct.getId());
}
}

saveall解决了前面的问题,但这里我又遇到了同样的问题。所以这个建议似乎使用了事务性的。我可以这样用吗,因为我用的是粗积存法?

@Transactional
    @GetMapping("/run")
public String run() {
    if(importer.runImporter() == 0){

        ...
        System.out.println(importElementaryFlowBases());
        System.out.println(importProcessTemplates());

        return "Import process has been executed";
    }
    else{
        return "Fail on import";
    }

}

public String importElementaryFlowBases() {
    System.out.println("Elementary flow bases import started");

    Set<ElementaryFlowBase> items =  importer.getElementaryFlowBases();
    elementaryFlowBaseRepository.saveAll(items);

    return "Elementary flow bases has been imported: + " + items.size() + "elements!";
}

public String importProcessTemplates() {
    System.out.println("Process templates import started");

    Set<ProcessTemplate> items =  importer.getProcessTemplates();

        processTemplateRepository.saveAll(items);

    return "Process templates has been imported: + " + items.size() + "elements!";
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题