mr.nothing
mr.nothing

Reputation: 5399

Hibernate (Spring JPA) child entities removal

I'm learning Hibernate (Spring) and facing strange issue with removing child entities from the parent one.

Here is what I have:

Parent entity:

@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:

@Entity
public class CompanyObject {

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

    @Enumerated(EnumType.STRING)
    ObjectType type;

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

Here is my table definitions:

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  

And, also, I have the following update method:

// 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;
    }
}

And as soon as I launch update method, I get the following error: java.sql.SQLWarning: Column 'company_id' cannot be null. I investigated this a little bit and found out that if I comment out company.getCompanyObjects().clear(); string it works ok, so it seems there is some problem with cascading delete action to company objects.

Could, please, somebody point me to my mistakes? Thanks.

Upvotes: 0

Views: 802

Answers (2)

Kirinya
Kirinya

Reputation: 245

You have mapped your entities Company and CompanyObject bidirectionally, i.e. both entities have a relation to the other entity.

In this case, there should only be one @Joincolumn and one entity must be selected as the owning entity, with the other entity marking the relation with a 'mappedby' (see http://docs.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html).

Upvotes: 1

Vimal Bera
Vimal Bera

Reputation: 10497

You are getting error because you are removing object's from List and then use the same List as a reference to your Company object. See below code :

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

Above code is used to define list which will be reference in your below code :

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));
    }

So your foreign key will always be null which is not permitted and throws exception.

And your code works when you comment out List#clear line because in that scenario, list already have some referenced objects which didn't modify.

Upvotes: 1

Related Questions