Hello,
I'm learning Hibernate from the Java Persistence w/Hibernate book, and I'm using annotations.
I have a parent class (Bucket) and a child class (Project). Simple 1:m entity association, but I'm getting an exception when I try to add a new Bucket complaining about constraints:
java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`spurs/project`, CONSTRAINT `project_ibfk_1` FOREIGN KEY (`bucketID`) REFERENCES `bucket` (`bucketID`))
Here's my database DDL for the two tables:
Create table Bucket (
bucketID Bigint NOT NULL AUTO_INCREMENT,
name Varchar(40) NOT NULL,
budget_amt Int NOT NULL,
balance Int NOT NULL,
budget_year Int NOT NULL,
Primary Key (bucketID)
) ENGINE = InnoDB;
Create table Project (
projectID Bigint NOT NULL AUTO_INCREMENT,
name Varchar(20) NOT NULL,
description Varchar(255) NOT NULL,
proj_type Varchar(10) NOT NULL,
proj_budget Int NOT NULL,
proj_spent Int NOT NULL,
date_requested Date NOT NULL,
proj_status Varchar(10) NOT NULL,
date_last_status_change Date NOT NULL,
requestor Varchar(20) NOT NULL,
approved_date Date,
bucketID Bigint NOT NULL DEFAULT 0,
Index AI_projectID (projectID),
Primary Key (projectID),
Index IX_pays_for (bucketID),
Foreign Key (bucketID) references Bucket (bucketID) on delete restrict on update restrict
) ENGINE = InnoDB;
And my Java code for the two classes (cut out unimportant getter/setters):
package foo;
// Generated Jan 15, 2007 10:50:12 AM by Hibernate Tools 3.2.0.beta8
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
/**
* Bucket generated by hbm2java
*/
@Entity
@Table(name = "bucket", catalog = "spurs", uniqueConstraints = {})
public class Bucket implements java.io.Serializable {
// Fields
private long bucketId;
private String name;
private int budgetAmt;
private int balance;
private int budgetYear;
private Set<Project> projects = new HashSet<Project>(0);
// Constructors
/** default constructor */
public Bucket() {}
/** minimal constructor */
public Bucket(String name, int budgetAmt, int balance, int budgetYear) {
this.name = name;
this.budgetAmt = budgetAmt;
this.balance = balance;
this.budgetYear = budgetYear;
}
// Property accessors
@Id
@Column(name = "bucketID", unique = true, nullable = false, insertable = true, updatable = true)
public long getBucketId() {
return this.bucketId;
}
public void setBucketId(long bucketId) {
this.bucketId = bucketId;
}
// <CLIP--Cut out accessors unimportant to this issue
@OneToMany(cascade={ CascadeType.ALL}, fetch = FetchType.LAZY, mappedBy = "bucket")
public Set<Project> getProjects() {
return this.projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
// Convenience method to handle both sides of the bucket/project relationship
public void addProject(Project project) {
projects.add(project);
project.setBucket(this);
}
}
package foo;
// Generated Jan 15, 2007 10:50:12 AM by Hibernate Tools 3.2.0.beta8
import java.util.Date;
import javax.persistence.*;
/**
* Project generated by hbm2java
*/
@Entity
@Table(name = "project", catalog = "spurs")
public class Project implements java.io.Serializable {
public enum PROJ_TYPE { BUGS, NEW_SYSTEM, ENHANCEMENT };
public enum PROJ_STATUS { REQUESTED, REJECTED, APPROVED, STOPPED, CANCELED, IN_WORK };
// Fields
private long projectId;
private Bucket bucket;
private String name;
private String description;
private PROJ_TYPE projType;
private int projBudget;
private int projSpent;
private Date dateRequested;
private PROJ_STATUS projStatus;
private Date dateLastStatusChange;
private String requestor;
private Date approvedDate;
// Constructors
/** default constructor */
public Project() {}
/** minimal constructor */
public Project(Bucket bucket, String name, String description, PROJ_TYPE projType,
int projBudget, int projSpent, String requestor) {
this.bucket = bucket;
this.name = name;
this.description = description;
this.projType = projType;
this.projBudget = projBudget;
this.projSpent = projSpent;
this.requestor = requestor;
this.projStatus = PROJ_STATUS.REQUESTED;
this.dateRequested = new Date();
this.dateLastStatusChange = dateRequested;
}
// Property accessors
@Id
@Column(name = "projectID", unique = true, nullable = false, insertable = true, updatable = false)
public long getProjectId() {
return this.projectId;
}
public void setProjectId(long projectId) {
this.projectId = projectId;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "bucketID", unique = false, nullable = false, insertable = true, updatable = true)
public Bucket getBucket() {
return this.bucket;
}
public void setBucket(Bucket bucket) {
this.bucket = bucket;
}
// Cut out unimportant accessors
}
And finally the code I'm using to create new bucket/project pair:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Bucket b = new Bucket("Reports", 5000, 5000, 2007);
Project p = new Project(b, "Spurs", "Project tracker", Project.PROJ_TYPE.NEW_SYSTEM,
25000, 0, "John Smith");
b.addProject(p);
session.save(b);
session.getTransaction().commit();
Its my understanding that the cascade option should take care of persisting child object p if I save bucket b. Of course I need to take care of setting both sides of the bidirectional association, which I think I did.
Thanks in advance for any help!
Greg
|