I have a big Java EE project with many db Entities and the JPA constraint checking has given me a lot of headaches!
To begin with, I have many entities with many types of dependencies (OneToOne, OneToMany). The whole project is for automatic analysis and calculation of metrics about source code from OSS repositories. (se.uom.gr/seagle).
So for example there is an entity Project and an entity Project_Timeline that holds historical analysis info.
This is the Project entity Class
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 255)
@Column(name = "name", unique = true)
private String name;
/**
* A remote URL from where this project is cloned.
* <p>
*/
@Size(max = 2048)
@Column(name = "remoteRepoPath", unique = true)
private String remoteRepoPath;
/**
* The metrics that should be calculated on the next execution.
* <p>
*/
@ManyToMany(mappedBy = "registeredProjects")
private Collection<Metric> registeredMetrics;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "project", orphanRemoval = true)
private Collection<Version> versions;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "project")
private ProjectInfo projectInfo;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "project", orphanRemoval = true)
private Collection<ProjectTimeline> timeLines;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "project", orphanRemoval = true)
private Collection<ProjectMetric> projectMetrics;
And this is the Project_TimeLine entity class
public class ProjectTimeline implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id")
private Integer id;
@Column(name = "timestamp")
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp;
@JoinColumn(name = "project_id", referencedColumnName = "id")
@ManyToOne(optional = false)
private Project project;
If I understood correctly the JPA guidelines the proper creation for these entities is:
Project p = new Project();
project.setName("some-java-oss");
project.setURL("http:////bla bla bla");
ProjectTimeline pi = new ProjectTimeline();
pi.setProject(p);
p.setProjectTimeline(pi);
entityManager.persist(p);
entityManager.persist(pi);
So I only to this, and expect for the JPA to handle the primary keys and make a successful JOIN.
BUT
JPA and Glassfish keep giving me the following error:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' cannot be null
Error Code: 1048
Call: INSERT INTO project_timeline (id, timestamp, action_id, project_id) VALUES (?, ?, ?, ?)
bind => [4 parameters bound]
Query: InsertObjectQuery(gr.uom.java.seagle.db.persistence.v2.ProjectTimeline[ id=null ])
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
... 266 more
Caused by:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' cannot be null
... 297 more
FULL error stack trace is here:
http://java.uom.gr/~chaikalis/documents/full_error_stacktrace.txt