Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring数据JPA实体创建两次_Java_Spring_Hibernate_Jpa - Fatal编程技术网

Java Spring数据JPA实体创建两次

Java Spring数据JPA实体创建两次,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我已经编写了一个服务方法importCategories(),它从数据库中检索类别列表,并递归地填充属性和父类别。我遇到的问题是,新类别创建了两次,除非我用@Transactional注释complete()。有人能解释一下为什么会这样吗?在将子对象添加到父对象之前,我先保存子对象,然后在子对象集合中保存具有CascadeType.ALL的父对象 型号: @Entity public class Category implements Identifiable<Integer> {

我已经编写了一个服务方法
importCategories()
,它从数据库中检索类别列表,并递归地填充属性和父类别。我遇到的问题是,新类别创建了两次,除非我用
@Transactional
注释
complete()
。有人能解释一下为什么会这样吗?在将子对象添加到父对象之前,我先保存子对象,然后在子对象集合中保存具有
CascadeType.ALL
的父对象

型号:

@Entity
public class Category implements Identifiable<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private Integer key;
    private String name;

    @ManyToOne
    private Category parent;

    @OneToMany(mappedBy="parent", cascade = {CascadeType.ALL})
    private List<Category> children = new ArrayList<Category>();

    public void add(Category category) {
        category.setParent(this);
        children.add(category);
    }

}
@实体
公共类类别实现了可识别的{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私有整数id;
私钥;
私有字符串名称;
@许多酮
私人类别家长;
@OneToMany(mappedBy=“parent”,cascade={CascadeType.ALL})
private List children=new ArrayList();
公共无效添加(类别){
类别。setParent(本);
添加(类别);
}
}
服务:

@Transactional
private void complete(Category category) {

    // ... (getting category info such as "name" and "parent key" from web service)

    category.setName(name);
    category = categoryRepository.saveAndFlush(category);

    if (category.getParent() == null) {

        Category parentCategory = new Category();
        parentCategory.setKey(parentKey);
        List<Category> categories = categoryRepository.findByKey(parentKey);
        if (categories.size() > 0) {
            parentCategory = categories.get(0);
        }

        parentCategory.add(category);
        parentCategory = categoryRepository.saveAndFlush(parentCategory);

        if (parentCategory.getParent() == null) {
            complete(parentCategory);
        }
    }
}

public void importCategories() {

    List<Category> list = categoryRepository.findAll();

    for (Category category : list) {
        complete(category);
    }

}
@Transactional
私人作废完成(类别){
//…(从web服务获取类别信息,如“名称”和“父密钥”)
类别.集合名(名称);
category=categoryRepository.saveAndFlush(类别);
if(category.getParent()==null){
类别parentCategory=新类别();
parentCategory.setKey(parentKey);
List categories=categoryRepository.findByKey(parentKey);
如果(categories.size()>0){
parentCategory=categories.get(0);
}
parentCategory.add(类别);
parentCategory=categoryRepository.saveAndFlush(parentCategory);
if(parentCategory.getParent()==null){
完整(家长类别);
}
}
}
公共无效导入类别(){
List List=categoryRepository.findAll();
用于(类别:列表){
完整(类别);
}
}

如果您有一个cascade-ALL类型,那么您不需要先保存子实体,只保存父实体

      category.getchildren().add(children)
      save(category)
此时,类别将保存/更新实体,并对子项执行相同的操作。 查看其他示例以了解hibernate级联的工作原理: