我试图在一个非常简单的Hibernate示例中填充一些实体对象。我的数据库由两个表组成,“Departments”(Id,Name)和“Employees”(Id,DepartmentsId,FirstName,LastName)。我的SQL查询只是员工到部门的左连接。
我已经按照Hibernate文档中的规定设置了注释,但每当我尝试序列化实体时,Hibernate就会进入一个无休止的循环,并最终引发StackOverflowerError异常。回答我的另一个问题的人能够确定堆栈溢出正在发生,因为“Department”对象包含一组“Employee”对象,每个对象包含一个“Department”对象,其中包含一组Employee对象等。
这种类型的双向关系应该是合法的,正如上面链接的留档所示(“部门”中的“映射者”参数应该是Hibernate的线索;我还尝试过使用下面代码中注释掉的“joinCol列”注释),我读过的其他东西表明Hibernate应该足够聪明,不会在这种情况下进入无休止的循环,但它不适用于我的示例。如果我通过从员工类中删除部门对象将双向关系更改为单向关系,一切都会正常工作,但显然这会导致大量功能的丢失。
我还尝试过放弃旧xml映射文件的注释并为子表设置“逆”参数,但它仍然会产生同样的问题。如何让这种双向关系以应有的方式工作?
部门:
package com.test.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.JoinTable;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.JoinColumn;
import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
@Entity
@Table(name="Departments"
,catalog="test"
)
public class Department implements java.io.Serializable {
private Integer id;
private String name;
public Set<Employee> employees = new HashSet<Employee>(0);
public Department() {
}
public Department(String name) {
this.name = name;
}
public Department(String name, Set employees) {
this.name = name;
this.employees = employees;
}
@Id @GeneratedValue(strategy=IDENTITY)
@Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="Name", nullable=false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(fetch=FetchType.LAZY, mappedBy="department")
/*@OneToMany
@JoinColumn(name="DepartmentsId")*/
public Set<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(Set employees) {
this.employees = employees;
}
}
员工:
package com.test.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.JoinTable;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="Employees"
,catalog="test"
)
public class Employee implements java.io.Serializable {
private Integer id;
private Department department;
private String firstName;
private String lastName;
public Employee() {
}
public Employee(Department department, String firstName, String lastName) {
this.department = department;
this.firstName = firstName;
this.lastName = lastName;
}
@Id @GeneratedValue(strategy=IDENTITY)
@Column(name="Id", unique=true, nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne
@JoinColumn(name="DepartmentsId", nullable=false, insertable=false, updatable=false)
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Column(name="FirstName", nullable=false)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Column(name="LastName", nullable=false)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
部门经理(包含HQL查询):
package com.test.controller;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import com.test.model.Department;
import com.test.util.HibernateUtil;
public class DepartmentManager extends HibernateUtil {
public List<Department> list() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Department> set = null;
try {
Query q = session.createQuery("FROM Department d JOIN FETCH d.employees e");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
set = (List<Department>) q.list();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
session.getTransaction().commit();
return set;
}
}
为了补充顶部的响应,我做了一个通用转换,由谁来为我做这项工作,将实体值传输到DTO对象,您只需使用映射实体中的相同名称来创建DTO字段。
这是源代码。
/***阿贡蒂os valore de campos通讯员de um Objetto para um outro Objetto de Destino。os*campos do Objetto de Destino que ja一人一天一次替代idos**@参数ObjetoOrigem*@参数ObjetoDestino*@返回*@抛出NegocioException*/
public static <T1, T2> T2 convertEntity(T1 objetoOrigem, T2 objetoDestino) throws NegocioException {
if (objetoOrigem != null && objetoDestino != null) {
Class<? extends Object> classe = objetoOrigem.getClass();
Class<? extends Object> classeDestino = objetoDestino.getClass();
Field[] listaCampos = classe.getDeclaredFields();
for (int i = 0; i < listaCampos.length; i++) {
Field campo = listaCampos[i];
try {
Field campoDestino = classeDestino.getDeclaredField(campo.getName());
campo.setAccessible(true);
campoDestino.setAccessible(true);
atribuiValorAoDestino(objetoOrigem, objetoDestino, campo, campoDestino);
} catch (NoSuchFieldException e) {
LOGGER.log(Logger.Level.TRACE, (Object) e);
continue;
} catch (IllegalArgumentException | IllegalAccessException e) {
LOGGER.error(e.getMessage(), e);
throw new NegocioException(e.getMessage(), EnumTypeException.ERROR);
}
}
}
return objetoDestino;
}
一般来说,您不应该序列化您的实体。循环依赖和代理使这变得困难。相反,您应该手动将您需要发送的数据传输到DTO(一个新的仅限数据的类),并将其改为序列化。它不会有惰性集合、代理等。
我有以下实体: 我尝试过创建@OneToOne(FetchType.lazy),但不起作用,它仍然提取不需要的信息。 如何避免获取复合对象? 我希望最终结果不包含Address对象,因为它在20个场景中需要一次,我可以分别获取它们。 任何想法,如何实现这一点。 谢谢
问题内容: 我有一个我认为应该很普遍的问题,但找不到答案。 我有2个对象:组和用户。我的课程如下所示: 现在,当我尝试从数据库中获取用户时,它带来了所有组,所有组都带来了所有用户,依此类推。最后,我遇到了stackoverflow异常。 如何解决此问题,并且仍然具有双向关联以及到达列表中对象的能力? 问题答案: 如果使用属性(无论如何都应使用)将双向关联的一侧设为关联的 拥有 侧,是否会遇到相同的
此特定环境下的程序:EJB3.0 JPA jersey Web Service 第一个实体: 第二实体: 当我拿到班级考试的学生名单时。例外情况是: 如果我更改fetch FetchType。懒惰例外情况是: 如何解决我的问题?
问题内容: 我知道python中的循环导入问题已经出现过很多次了,我已经阅读了这些讨论。在这些讨论中反复提出的意见是,循环导入表明设计不良,应重新组织代码以避免循环导入。 有人可以告诉我在这种情况下如何避免循环导入吗?:我有两个类,并且我希望每个类都有一个构造函数(方法),该构造函数接受另一个类的实例并返回该类的实例。 更具体地说,一类是可变的,一类是不变的。哈希,比较等需要不可变的类。可变类也需
我在服务器日志中收到一个警告“firstResult/max结果指定集合获取;在内存中应用!”。然而一切正常。但我不想要这个警告。
但是这两种方法都不起作用(第一种方法导致ParseeRoreXception,第二种方法在传递给方法的值中产生双反斜杠)。