假设我有两个名为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);
答案 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关联的默认方式。