Hibernate onetoMany映射检索链中的所有结果

时间:2013-09-17 17:55:00

标签: hibernate

假设我有两个名为employee和phone_number的表,员工可以有多个号码。

我有两张桌子,例如:

1) employee
columns:
id
name

2) phone_number
columns:
employee_id(FK)
phone_number_type
phone_number

employee和phone_number有一对多的映射(phone_number中的employee_id列充当FK)

我在模型类中定义了以下注释。

@Entity
@Table(name="employee")
public class Employee
@Id
@GeneratedValue
private Integer id;

@OneToMany(fetch = FetchType.LAZY, mappedBy="employee_id")
@JoinColumn(name = "ID")
private Set<PhoneNumber> phonenumbers = new HashSet<PhoneNumber>(0);

public Set<PhoneNumber> getPhonenumbers() {
return phonenumbers; 
}

public void setPhoneNumbers(Set<PhoneNumber> phonenumbers) {
this.phonenumbers = phonenumbers; 
}

Class PhoneNumber

@Entity
@Table(name="phone_number")
public class PhoneNumber {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employee_id")
private Employee employeeid;

public Employee getEmployeeid() {
return this.employeeid;
}

public void setEmployeeid(Employee employeeid) {
this.employeeid = employeeid;
}

我的问题是当我检索所有员工或特定员工时,我也想检索他们的电话号码。目前,当我在调试模式下运行时,我看不到正在填充的电话号码。我在springmvc框架中运行hibernate,我通过以下代码检索员工:

@Override
@SuppressWarnings("unchecked")
public List<Employees> getEmployees() {
  // TODO Auto-generated method stub
  return getCurrentSession().createQuery("from Employees").list();
}

我需要做些额外的事情才能返回phone_numbers。我的最终目标是在视图中以表格格式显示员工和电话号码。

谢谢

当我做“fetch = EAGER”时,我试图调试,但我没有看到值。如何确保它正在提取手机数据?

List<Employees> _employees= employeeService.getEmployees();
        for (Employees o: _employees) {
            java.util.Set<PhoneNumber> a = o.getPhonenumbers();
        }

我发现了我犯的错误,但我遇到了另一个问题。 我的错误是employee_id字段是FK,但它没有正确填充。但是,此列不是phone_number表中的主键。

我将phone_number更改为:

@Entity
@Table(name="phonenumber")
public class Phonenumber {


    @EmbeddedId
    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "EMPLOYEEID")
    private Employee employeeid;

但是,我现在收到以下错误: 引起:org.hibernate.MappingException:Composite-id类必须实现Serializable:

我能够摆脱这个错误,但我遇到了另一个有趣的错误。它只选择了电话号码的第一行。

@Entity
@Table(name="phonenumber")
public class Phonenumber implements Serializable {

    @Column(name="key")
    private String key;

    @Column(name="value")
    private String value;

    @Id
    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "EMPLOYEEID")
    private Employee employee;

员工

@Entity
@Table(name="employee")
public class Employee{

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(mappedBy = "employeeid", fetch = FetchType.EAGER)
    private Set<Phonenumber> phonenumbers= new HashSet<Phonenumber>(0); 

5 个答案:

答案 0 :(得分:1)

  • 使用HQL可以实现如下:

    createQuery("from employee e left join fetch e.phonenumbers")

  • 作为替代方案,您可以使用EAGER loading。但是,要非常小心并考虑其影响。   它可能会影响性能,因为它会加载所有相关实体。


@JoinColumn中没有必要,因为您通过mappedBy说明了如何加入实体。在大多数情况下,@JoinColumn用于单向关系,或者当您没有mappedBy时。

请从Phonenumber的员工列中删除@Id,并让id成为主键。

@Entity
@Table(name="phonenumber")
public class Phonenumber implements Serializable {

    @Column(name="key")
    private String key;

    @Column(name="value")
    private String value;

    @Id
    @GeneratedValue
    private Integer id;


    @ManyToOne(fetch=FetchType.EAGER)
    private Employee employee;

}

答案 1 :(得分:1)

我遇到了同样的问题。通过允许休眠创建一个新表作为引用来解决

@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "employee_phonenumber", 
    joinColumns = @JoinColumn(name = "empid"), 
    inverseJoinColumns = @JoinColumn(name = "phoneid"))
private Set<PhoneNumber> phonenumbers = new HashSet<PhoneNumber>(0);

答案 2 :(得分:0)

您是否尝试过将抓取类型更改为急切?

FetchType.LAZY
to
FetchType.EAGER

您可以打开调试以通过设置

来显示正在执行的基础sql语句

<property name="show_sql">true</property>

在hibernate配置中。用它来检查。

答案 3 :(得分:0)

我最后添加了一个名为“id”的列,这是员工的主键,这似乎解决了我遇到的问题。虽然我不太喜欢它的解决方案。

答案 4 :(得分:0)

要填充Phonenumber,您需要调用employee.getPhonenumbers()。size()。换句话说,只有在第一次访问时才填充phonenumber集合,而不是在加载employee对象时填充。这种按需访问方式称为延迟加载,是@OneToMany和@ManyToMany关联的默认方式。