休眠一对多关系

Posted

技术标签:

【中文标题】休眠一对多关系【英文标题】:Hibernate OneToMany Relation 【发布时间】:2014-03-03 12:51:32 【问题描述】:

我遇到了休眠 OneToMany 关系的问题。由于某种原因,hibernate 无法以正确的方式保存关系。这是两个类:

@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();


二等:

@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();


该问题仅出现在 Project 和 Workingpackage 之间的 OnetoMany 关系中。由于某种原因,hibernate没有正确保存数据库中的对象,工作包表中缺少projectID,因此没有链接。

编辑:我之前有 getter 和 setter,现在发布了整个类...

编辑2:

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

二等:

@ManyToOne
private Project project;

为我工作....

【问题讨论】:

你缺少 getter 和 setter ,尝试用 hibernate 生成 pojo 类,看看有什么不同 【参考方案1】:

您的映射将 WorkingPackage 定义为关系的所有者。 仅当设置了 WorkingPackage.project 时才会更新列 projectId(如果将元素添加到 Project.workingPackages 则不会)。

请参阅:http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html: 该关联可以是双向的。在双向关系中,一方(并且只有一方)必须是所有者:所有者负责关联列的更新。要声明一方不负责关系,则使用属性 mappedBy。

【讨论】:

以上是关于休眠一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

一对多的连接列为空休眠

jpa休眠一对多双向[重复]

休眠一对多映射注释问题

Hibernate 一对多关系级联删除

休眠一对多关联删除

一对多和一对多连续映射的休眠条件查询 - 表或视图不存在