Question

I got a problem with hibernate OneToMany relation. For some reason hibernate has problems saving the Relation in the right way. Here are the two classes:

@Entity
@Table
public class Project {

@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
@Column(unique = true, nullable = false)
private int projectId;

@Column(unique = true, nullable = false)
private String name;

@ManyToMany(fetch = FetchType.EAGER, mappedBy = "projects", targetEntity = User.class)
private Set<User> users;

@OneToMany(fetch = FetchType.EAGER, mappedBy = "project", 
        cascade = CascadeType.ALL, targetEntity = WorkingPackage.class)
private Set<WorkingPackage> workingPackages;

/**
 * Default Constructor. Creates an empty object.
 */
public Project() {
    // nothing to do here!
}

/**
 * Convenience Constructor. Use this constructor to create a new {@link Project} object.
 * 
 * @param name  The name of the project. May not be null.
 */
public Project(String name) {
    this.name = name;
}

/**
 * The id is the unique identifier for the {@link Project} in the database. DO NOT set the 
 * id manually since it will be generated by Hibernate.
 * 
 * @return  The unique identifier for the project.
 */
public int getProjectId() {
    return projectId;
}

/**
 * The id is the unique identifier for the {@link Project} in the database. DO NOT set the 
 * id manually since it will be generated by Hibernate.
 * 
 * @param projectId  The unique identifier for the project.
 */
public void setProjectId(int projectId) {
    this.projectId = projectId;
}

/**
 * Refers to the name of the {@link Project}.
 * 
 * @return  The name of the project.
 */
public String getName() {
    return name;
}

/**
 * Refers to the name of the {@link Project}.
 * 
 * @param name  The name of the project.
 */
public void setName(String name) {
    this.name = name;
}


/**
 * Gets the working packages.
 *
 * @return the working packages
 */
public Set<WorkingPackage> getWorkingPackages() {
    return workingPackages;
}

/**
 * Sets the working packages.
 *
 * @param workingPackages the new working packages
 */
public void setWorkingPackages(Set<WorkingPackage> workingPackages) {
    this.workingPackages = workingPackages;
}

/**
 * Gets the users.
 *
 * @return the users
 */
public Set<User> getUsers() {
    return users;
}

/**
 * Sets the users.
 *
 * @param users the new users
 */
public void setUsers(Set<User> users) {
    this.users = users;
}

@Override
public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if (!(other instanceof Project)) {
        return false;
    }

    final Project project = (Project) other;

    if (!project.getName().equals(getName())) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
    return getName().hashCode();
}
}

Second class:

@Entity
@Table
public class WorkingPackage {

@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
@Column(unique = true, nullable = false)
private int workingPackageId;

@Column(nullable = false)
private String name;

@ManyToOne(fetch = FetchType.EAGER)
@Cascade({CascadeType.ALL })
@JoinColumn (name = "projectId")
private Project project;

/**
 * Default Constructor. Creates an empty object.1
 */
public WorkingPackage() {
    // nothing to do here!
}

/**
 * Convenience Constructor. Use this constructor to create a new {@link WorkingPackage} object.
 * 
 * @param name  The name of the project. May not be null.
 */
public WorkingPackage(String name) {
    this.name = name;
}

/**
 * The id is the unique identifier for the {@link WorkingPackage} in the database. DO NOT set the 
 * id manually since it will be generated by Hibernate.
 * 
 * @return  The unique identifier for the project.
 */
public int getWorkingPackageId() {
    return workingPackageId;
}

/**
 * The id is the unique identifier for the {@link WorkingPackage} in the database. DO NOT set the 
 * id manually since it will be generated by Hibernate.
 * 
 * @param workingPackageId  The unique identifier for the project.
 */
public void setWorkingPackage(int workingPackageId) {
    this.workingPackageId = workingPackageId;
}

/**
 * Refers to the name of the {@link WorkingPackage}.
 * 
 * @return  The name of the working package.
 */
public String getName() {
    return name;
}

/**
 * Refers to the name of the {@link WorkingPackage}.
 * 
 * @param name  The name of the working package.
 */
public void setName(String name) {
    this.name = name;
}

/**
 * Refers to the project of the {@link WorkingPackage}.
 * 
 * @return  The project of the working package.
 */
public Project getProject() {
    return project;
}

/**
 * Refers to the project of the {@link WorkingPackage}.
 * 
 * @param project  The name of the working package.
 */
public void setProject(Project project) {
    this.project = project;
}

@Override
public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if (!(other instanceof WorkingPackage)) {
        return false;
    }

    final WorkingPackage workingPackage = (WorkingPackage) other;

    if (!workingPackage.getName().equals(getName())) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
    return getName().hashCode();
}
}

The problem occurs only at the OnetoMany relation between Project and Workingpackage. For some reason hibernate is not saving the objects in the database correctly, the projectID is missing in the workingpackage table, so that there is no link.

EDIT: I had the getters and setters before, posted the whole classes now...

EDIT2:

@OneToMany
@Cascade({CascadeType.SAVE_UPDATE })
@JoinColumn(name = "project_id")
private Set<WorkingPackage> workingPackages;

Second class:

@ManyToOne
private Project project;

works for me....

Was it helpful?

Solution

Your mapping defines WorkingPackage as the owner of the relationship. The column projectId will be updated only if WorkingPackage.project is set (not if an element is added to Project.workingPackages).

See : http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html : The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top