-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Newbie: Parent/Child insert fails--using annotations
PostPosted: Mon Jan 15, 2007 2:56 pm 
Newbie

Joined: Thu Jan 11, 2007 7:38 pm
Posts: 4
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


Top
 Profile  
 
 Post subject: Got it!
PostPosted: Mon Jan 15, 2007 9:37 pm 
Newbie

Joined: Thu Jan 11, 2007 7:38 pm
Posts: 4
Ok, fixed my own issue. I created a trivial Parent/Child pair of classes and tables to get to the bare essentials. The trivial example worked but not the real classes.

At first I thought it was an InnoDB vs. MyISAM issue--nope.

It turned out the problem was that my DB DDL generator tool was creating some kind of automatic index on the FK of the child table. I'm not a DBA so I don't know why that's a problem, but I noticed my trivial example didn't have it and when I removed it from the real tables--it worked.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 9:38 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That mapping implements one-to-many where the many-side is the owner: useful for associations like car to model (one model has thousands of cars, but that's not normally useful: what's important is that a car has a specific model). What you want is an association where the one-side is the owner.

Have a look in the annotation ref docs section 2.2.5.3.2.1, "Bidirectional". You've implemented the first example, you need to implement the second example.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.