When running the following code, I get a org.hibernate.exception.ConstraintViolationException exception
complaining that
org.h2.jdbc.JdbcSQLException: NULL not allowed for column "SECONDARYELEMENTS_ID";
I know that this is caused by having two @ManyToMany relations from the Container object to the Element objects. If I remove
@ManyToMany(cascade = CascadeType.ALL)
List<Element> secondaryElements;
from the the Container class everything runs fine.
What am I missing here?
Let me know if you need more information.
@Transactional
public class JPA2Runner {
//hidding Spring Data JPA repository
@Autowired
ContainerDAO containerDAO;
public boolean run() throws Exception{
Container container1 = new Container( );
Container container2 = new Container( );
Element element1 = new Element( container1, container2);
Element element2 = new Element( container2, container1);
container1.getPrimaryElements().add(element1);
container1.getSecondaryElements().add(element2);
container2.getPrimaryElements().add(element2);
container2.getSecondaryElements().add(element1);
containerDAO.saveContainer(container1);
return true;
}
}
@Entity
public class Container extends AbstractEntity {
@ManyToMany(cascade = CascadeType.ALL)
List<Element> primaryElements;
@ManyToMany(cascade = CascadeType.ALL)
List<Element> secondaryElements;
public Container( ){
primaryElements =new ArrayList<Element>();
secondaryElements = new ArrayList<Element>();
}
}
@Entity
public class Element extends AbstractEntity {
@ManyToOne(cascade = CascadeType.ALL)
private Container dedicatedContainer1;
@ManyToOne(cascade = CascadeType.ALL)
private Container dedicatedContainer2;
public Element(){}
public Element(Container container1, Container container2){
this.dedicatedContainer1 = container1;
this.dedicatedContainer2 = container2;
}
}
Update 1: Could it be that it is required to specify the @JoinTable in case there are multiple relations to the same type?
Update 2: Thanks to @ducksteps hints and comments I was able to find a workaround for the issue. The problem is that the above definition generates a join table with keys for both element lists, i.e.
create table Container_Element (Container_id bigint not null, secondaryElements_id bigint not null, primaryElements_id bigint not null)
however, saving a container generates the following insert in the join table
insert into Container_Element (Container_id, primaryElements_id) values (?, ?)
which causes the ConstraintViolation exception. A fix seems to be to explicitly define two Join tables using
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="Container_PrimaryElements")
List<Element> primaryElements;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="Container_SecondaryElements")
List<Element> secondaryElements;
which seems to work.
However, I am still wondering whether
- there are better solutions for this issue?
- using a join table for both ManyToMany relations "should" actually work (according to the specification)?