我们有 2 个表(一个 Activity 表和一个存档表),它们具有相同的结构(例如 Employee
和 EmployeeArchive
)。为了能够利用公共(public)代码来使用两个表的结果,我们有一个抽象父类,它定义了所有方法和注释。
我们希望能够执行对两个表使用相同查询并将结果合并在一起的查询。
我们有另一个实体/表(例如 Organization
)与 onetomany
有 manytoone
/Employee
双向关系; Organization
有一个 List
的 Employee
s,每个员工都有一个组织。
当通过关联获取组织的员工时,我们只需要 Activity 表中的员工而不是文件。
有没有办法实现我们正在尝试的目标或可行的解决方法?
我们尝试了@MappedSuperclass
、@Entity
/@InheritanceType.TABLE_PER_CLASS
的各种实现来尝试实现我们想要的。每个实现几乎都能实现我们想要的,但并不完全。例如,为了能够查询两个表,我们可以有一个带有 Entity
的抽象父 InheritanceType.TABLE_PER_CLASS
,但是我们不能在 mappedBy
中拥有与 Employee
的 Organization
关系。我们可以使用 MappedSuperclass
作为父级来建立正确的关系,但是我们无法通过联合查询 Archive
和 Active
表。
这基本上是我们试图布局的内容:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEmployee {
@ManyToOne
@JoinColumn(name="employeeId", nullable=false)
Organization org;
...
}
@Entity
public class Employee extends AbstractEmployee {
}
@Entity
public class EmployeeArchive extends AbstractEmployee {
}
@Entity
public class Organization {
@OneToMany(cascade=ALL, mappedBy="org")
List<Employee> employees;
...
}
代码
public List<AbstractEmployee> getAllEmployees()
{
Query query = em.createQuery("SELECT e FROM AbstractEmployee e where e.name = ‘John’", AbstractEmployee.class);
return query.getResultList();
}
public List<Organization> getOrganizations()
{
Query query = em.createQuery("SELECT e FROM Organization o ", Organization.class);
List<Organization> orgs = query.getResultList();
// fetch or eager fetch the Employees but only get the ones from the active employee table
return orgs;
}
我们还尝试让父类扩展
MappedSuperclass
并将实现和注释放在 MappedSuperclass
中,但我们得到了 AnnotationException
的 Organization
关系 @MappedSuperclass
public abstract class AbstractMapped {
@ManyToOne
@JoinColumn(name="employeeId", nullable=false)
Organization org;
}
@Entity
@Inheritance(@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS))
public abstract class AbstractEmployee extends AbstractMapped {
... `Constructors` ...
}
在部署时,我们得到以下异常:
Caused by org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: Employee.org in Organizaztion.employees
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:685)
最佳答案
您可以通过更改 Organization
到 Employee
的映射来实现这一点,以便它使用关系表,而不是在 org
表中包含 Employee
字段。请参阅 Hibernate documentation 中的示例,对于您来说,它看起来像:
@Entity
public class Organization {
@OneToMany(cascade=ALL)
@JoinTable(
name="ACTIVE_EMPLOYEES",
joinColumns = @JoinColumn( name="ORGANIZATION_ID"),
inverseJoinColumns = @JoinColumn( name="EMPLOYEE_ID")
)
List<Employee> employees;
...
}
但是 ,我不得不说,我认为用两个表来表示当前和存档的员工是一个坏主意。这对我来说听起来像是一种“软删除”的情况,最好使用表内标志(IS_ACTIVE 或其他东西)来处理。那么你就没有这些奇怪的抽象类来执行你的查询、具有相同类型数据的多个表等。这个策略的一些描述 is here 。
然后,您可以使用您已经获得的非连接表映射,并使用
@Where
注释将组织中的员工限制为 IS_ACTIVE 设置为 true 的员工。这种方法的一个例子 is here.