如何使用Hibernate注释@ManyToOne和@OneToMany进行关联 [英] How to use Hibernate annotations @ManyToOne and @OneToMany for associations

查看:98
本文介绍了如何使用Hibernate注释@ManyToOne和@OneToMany进行关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用本教程学习Spring,Hibernate,Maven:Chad Lung:一个使用Netbeans 7,JUnit, Maven,HSQLDB,Spring和Hibernate 。它工作正常,但我需要建立一对多的关系(一名员工有很多任务)。我已经尝试了很多示例,但仍然无法理解如何使代码生效:

Employee.java:

  package com.giantflyingsaucer.simplespringhibernate.entity; 

import javax.persistence。*;
import java.io.Serializable;
import java.util.List;

@Entity
@Table(name =Employees)
public class Employee实现Serializable {

private Integer employeeId;
私人列表< Task>任务;

@Id
@Column(name =idEmployees,nullable = false)
public Integer getEmployeeId(){
return this.employeeId;
}

public void setEmployeeId(Integer employeeId){
this.employeeId = employeeId;
}

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name =idEmployees)
public List< Task> getTasks(){
返回任务;


Task.java:

  package com.giantflyingsaucer.simplespringhibernate.entity; 

import javax.persistence。*;
import java.io.Serializable;

@Entity
@Table(name =Tasks)
public class Task实现Serializable {

private Integer taskId;
私人雇员雇员;


@Id
@Column(name =idTasks,nullable = false)
public Integer getTaskId(){
return this.taskId;
}

public void setTaskId(Integer taskId){
this.taskId = taskId;

$ b @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =TasksIdEmployees)
public Employee getEmployee(){return employee;}

}

db-config.xml:

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :p =http://www.springframework.org/schema/p
xmlns:context =http://www.springframework.org/schema/contextxmlns:tx =http:// www.springframework.org/schema/tx
xsi:schemaLocation =http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans。 xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework .org / schema / context http://www.springframework.org/schema/context/spring-context-3.0.xsd
>
< bean id =dataSourceclass =com.mchange.v2.c3p0.ComboPooledDataSource
destroy-method =close>

< property name =driverClass>
< value> $ {jdbc.driver.className}< /值>
< / property>
< property name =jdbcUrl>
< value> $ {jdbc.url}< /值>
< / property>
< property name =user>
<值> $ {jdbc.username}< /值>
< / property>
< property name =password>
<值> $ {jdbc.password}< /值>
< / property>
< / bean>
< bean id =sessionFactory
class =org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean>
< property name =dataSource>
< ref bean =dataSource/>
< / property>
< property name =packagesToScanvalue =com.giantflyingsaucer.simplespringhibernate.entity/>
< property name =hibernateProperties>
<道具>
< prop key =hibernate.dialect> $ {jdbc.hibernate.dialect}< / prop>
< prop key =hibernate.hbm2ddl.auto> update< / prop>
< prop key =hibernate.show_sql> false< / prop>
< /道具>
< / property>
< / bean>
< bean id =transactionManager
class =org.springframework.orm.hibernate3.HibernateTransactionManager>
< property name =sessionFactory>
< ref bean =sessionFactory/>
< / property>
< / bean>
< tx:annotation-driven />



MySQL表格:

  CREATE TABLE employees(
`idEmployees` int(11)NOT NULL,
PRIMARY KEY(`idEmployees`)
);

CREATE TABLE任务(
`idTasks` int(11)NOT NULL,
`TasksIdEmployees` int(11)DEFAULT NULL,
PRIMARY KEY(`idTasks` ),
KEY`FkTasksEmployees_idx`(`TasksIdEmployees`),
CONSTRAINT`FkTasksEmployees` FOREIGN KEY(`TasksIdEmployees`)REFERENCES`employees`(`idEmployees`)ON DELETE NO ACTION ON UPDATE NO ACTION
);

非常感谢!



我发现在NetBeans中自动生成映射文件和POJO的答案:

pre $ Employee.java
@OneToMany(fetch = FetchType.LAZY,mappedBy =employees)
public List< Task> getTasks(){
返回this.tasks;
}

public void setTasks(List< Task> tasks){
this.tasks = tasks;
}

// Task.java:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =TasksIdEmployees)
public员工getEmployees(){
返回this.employee;
}

public void setEmployees(Employee employee){
this.employee = employee;


解决方案



  @OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name =idEmployees)
公开列表< Task> getTasks(){
返回任务;
}

有两个原因是错误的。


  1. @JoinColumn(name =idEmployees)表示:this OneToMany使用名为 idEmployees 的连接列(即外键)进行映射。但连接列未命名为idEmployees。 idEmployees是Employee表的主键。连接列名称是 TasksIdEmployees 。使用正确的名称可以使映射正确处理单向OneToMany关联。但是这种关联是双向的,这导致了第二个原因......在一个双向关联中,没有必要(也是一个错误)重复关联两侧的映射信息。一方(多方)必须是该协会的所有者并定义该映射。另一方面必须简单地说:反过来看另一方如何映射这个关联。这是通过mappedBy属性完成的,该属性告诉Hibernate在关联所有者的另一端字段或属性的名称:

      @OneToMany(mappedBy =employee)
    public List< Task> getTasks(){
    返回任务;
    }


请注意,LAZY是toMany关联的默认值,所以不需要指定它。

I am learning Spring, Hibernate, Maven by using this tutorial: Chad Lung: A project using Netbeans 7, JUnit, Maven, HSQLDB, Spring and Hibernate. It works ok but I need to make one-to-many relationship (one Employee have many Tasks). I have tried many examples but still can't get idea how to make my code work:

Employee.java:

package com.giantflyingsaucer.simplespringhibernate.entity;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

@Entity
@Table(name = "Employees")
public class Employee implements Serializable {

    private Integer employeeId;
    private List<Task> tasks;

    @Id
    @Column(name = "idEmployees", nullable=false)
    public Integer getEmployeeId() {
        return this.employeeId;
    }

    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name="idEmployees")
    public List<Task> getTasks() {
        return tasks;
    }
}

Task.java:

package com.giantflyingsaucer.simplespringhibernate.entity;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "Tasks")
public class Task implements Serializable {

    private Integer taskId;
    private Employee employee;


    @Id
    @Column(name = "idTasks", nullable=false)
    public Integer getTaskId() {
        return this.taskId;
    }

    public void setTaskId(Integer taskId) {
        this.taskId = taskId;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TasksIdEmployees")
    public Employee getEmployee() {return employee;}

}

db-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">

    <property name="driverClass">
        <value>${jdbc.driver.className}</value>
    </property>
    <property name="jdbcUrl">
        <value>${jdbc.url}</value>
    </property>
    <property name="user">
        <value>${jdbc.username}</value>
    </property>
    <property name="password">
        <value>${jdbc.password}</value>
    </property>
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
    <property name="packagesToScan" value="com.giantflyingsaucer.simplespringhibernate.entity" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>
    </property>
</bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref bean="sessionFactory" />
    </property>
</bean>
<tx:annotation-driven />

MySQL tables:

CREATE TABLE employees (
`idEmployees` int(11) NOT NULL,
PRIMARY KEY (`idEmployees`)
);

CREATE TABLE tasks (
`idTasks` int(11) NOT NULL,
`TasksIdEmployees` int(11) DEFAULT NULL,
PRIMARY KEY (`idTasks`),
KEY `FkTasksEmployees_idx` (`TasksIdEmployees`),
CONSTRAINT `FkTasksEmployees` FOREIGN KEY (`TasksIdEmployees`) REFERENCES `employees`   (`idEmployees`) ON DELETE NO ACTION ON UPDATE NO ACTION
);

Thanks a lot!

I found an answer by autogenerating Mapping files and POJOs in NetBeans:

// Employee.java:
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
    public List<Task> getTasks() {
        return this.tasks;
    }

    public void setTasks(List<Task> tasks) {
        this.tasks = tasks;
    }

// Task.java:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TasksIdEmployees")
public Employee getEmployees() {
    return this.employee;
}

public void setEmployees(Employee employee) {
    this.employee = employee;
}

解决方案

What's wrong is the following:

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="idEmployees")
public List<Task> getTasks() {
    return tasks;
}

And it's wrong for two reasons.

  1. @JoinColumn(name="idEmployees") means: this OneToMany is mapped using a join column (i.e. a foreign key) named idEmployees. But the join column is not named idEmployees. idEmployees is the primary key of the Employee table. The join column name is TasksIdEmployees. Putting the right name would make the mapping correct for a unidirectional OneToMany association. But the association is bidirectional, which leads to the second reason...

  2. In a bidirectional association, there is no need (and it's a bug) to repeat the mapping information on both sides of the association. One side (the many side) must be the owner of the association and define the mapping. The other side must be the inverse side by simply saying: go see at the other side how this association is mapped. This is done using the mappedBy attribute, which tells Hibernate the name of the field or property on the other side which is the owner of the association:

    @OneToMany(mappedBy = "employee")
    public List<Task> getTasks() {
        return tasks;
    }
    

Note that LAZY is the default for toMany associations, so it's unnecessary to specify it.

这篇关于如何使用Hibernate注释@ManyToOne和@OneToMany进行关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆