2016-10-04 154 views
0

我正在學習Hibernate(Spring),並且面臨着從父類刪除子實體的奇怪問題。Hibernate(Spring JPA)子實體的刪除

以下是我有:

父實體:

@Entity 
public class Company { 

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

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "company_id", referencedColumnName = "id") 
    List<CompanyObject> companyObjects; 
} 

實體Child:

@Entity 
public class CompanyObject { 

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

    @Enumerated(EnumType.STRING) 
    ObjectType type; 

    @ManyToOne 
    @JoinColumn(name = "company_id") 
    Company company; 
} 

這裏是我的表定義:

CREATE TABLE `company` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`), 
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 

CREATE TABLE `company_object` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `company_id` bigint(20) NOT NULL, 
    `type` varchar(50) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `FK__company` (`company_id`), 
    CONSTRAINT `FK__company` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

而且,還,我有以下update方法:

// some code here 
public void update(CompanyDto dto) { 
    Company company = repository.getCompanyById(companyId); 
    repository.save(dto.merge(company)); 
} 
// some code here 


public class CompanyDto { 
    private List<CompanyObjectDto> companyObjects = new ArrayList<>(); 

    public Company merge(Company company) {   
     company.getCompanyObjects().clear(); 
     for (CompanyObjectDto dto : companyObjects) { 
      company.getCompanyObjects().add(dto.to(company)); 
     } 
     return company; 
    } 
} 

public class CompanyObjectDto { 
    ObjectType type; 

    public CompanyObject to(Company company) { 
     CompanyObject object = new CompanyObject(); 
     object.setType(this.getType()); 
     object.setCompany(company); 
     return object; 
    } 
} 

而且我只要一推出update方法,我得到以下錯誤:java.sql.SQLWarning: Column 'company_id' cannot be null。我仔細研究了一下,發現如果我註釋掉company.getCompanyObjects().clear();字符串,它就可以正常工作,所以看起來對公司對象的級聯刪除操作存在一些問題。

請問有人能指出我的錯誤嗎?謝謝。

+1

雙向映射時,應該只有一個@Joincolumn,並且缺少'mappedby'。 – Kirinya

+0

這不是導致問題的原因,但是除非您向'OneToMany'註釋(列表所在的位置)添加',orphanRemoval = true',否則您將發現它不會刪除您從列表中移除的行。沒有它就是什麼會導致你的下一個問題。 – coladict

+0

@Kirinya,謝謝,工作。你能否提出你的答案,以便我可以相應地標記它? –

回答

1

由於您從List中刪除對象,然後使用相同的List作爲您的Company對象的引用,因此會出現錯誤。請參見下面的代碼:

private List<CompanyObjectDto> companyObjects = new ArrayList<>(); //Stmt 1 

上面的代碼是用來定義列表,它會在你的下面的代碼參考:

company.getCompanyObjects().clear(); //It will clear out all objects 
    for (CompanyObjectDto dto : companyObjects) { //Iterating over empty list defined in stmt 1. 
     company.getCompanyObjects().add(dto.to(company)); 
    } 

所以,你的外鍵將永遠是空這是不允許的,並拋出異常。

而且您的代碼在您註釋掉List#clear行時起作用,因爲在該情況下,列表中已經有一些未修改的引用對象。

+0

感謝您的回覆,但不幸的是,我不明白我的理解。你是否說我需要將'new ArrayList()'賦值給'companyObjects'來讓hibernate做我想做的事? –

+0

啊,我想我明白了。其實'companyObjects'不是空的。有一些數據來自Web界面。 –