采用TABLE_PER_CLASS继承查询两张数据库表时抛出异常
问题分析与解决方案
问题根源
你遇到的Table 'r_db.TableBase' doesn't exist异常,核心原因是使用InheritanceType.TABLE_PER_CLASS继承策略时,Hibernate对非抽象父实体类的处理逻辑:
- 当父类
TableBase被标记为@Entity且非抽象时,Hibernate会将其视为具体实体,默认认为数据库中存在对应的TableBase表; - 执行
select e from TableBase e查询时,Hibernate会尝试访问这张不存在的表,从而抛出异常。
最优解决方案:将父类改为抽象类
只需把TableBase改为抽象类,保留原有的@Entity和TABLE_PER_CLASS注解即可。此时Hibernate会识别这是一个抽象父类,不会去寻找对应的物理表,而是自动通过UNION ALL合并所有子类对应的表(TABLE_1、TABLE_2)的数据。
修改后的父类代码:
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class TableBase { @Id @Column(name="NAME") private String name; @Column(name="PHONE") private String phoneNumber; public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phone) { this.phoneNumber = phone; } }
原查询代码无需任何修改,执行后即可正常返回两张表的合并数据。
备选解决方案
如果无法将父类改为抽象类,可以选择以下两种方式:
方式1:改用@MappedSuperclass
将父类的@Entity注解替换为@MappedSuperclass,此时父类不再是JPA实体,仅作为子类的字段映射模板。需要手动合并两个子类的查询结果:
父类修改:
@MappedSuperclass public class TableBase { // 字段和方法保持不变 }
查询代码调整:
public ArrayList<TableBase> getUsers(){ AppEntityManager appEntMgr = AppEntityManager.getAppEntityManager(); appEntMgr.startTransaction(); List<Table1> table1Data = appEntMgr.createQuery("select e from Table1 e", Table1.class) .setFirstResult(0) .setMaxResults(10) .getResultList(); List<Table2> table2Data = appEntMgr.createQuery("select e from Table2 e", Table2.class) .setFirstResult(0) .setMaxResults(10) .getResultList(); ArrayList<TableBase> result = new ArrayList<>(); result.addAll(table1Data); result.addAll(table2Data); // 若需要全局分页,需自行处理数据截取逻辑 return result; }
方式2:使用显式UNION查询
保留父类原注解,通过JPQL的UNION语法直接查询两个子类并合并结果:
查询代码修改:
public ArrayList<TableBase> getUsers(){ AppEntityManager appEntMgr = AppEntityManager.getAppEntityManager(); appEntMgr.startTransaction(); String jpql = "SELECT e FROM Table1 e UNION SELECT e FROM Table2 e"; return (ArrayList<TableBase>) appEntMgr.createQuery(jpql, TableBase.class) .setFirstResult(0) .setMaxResults(10) .getResultList(); }
内容的提问来源于stack exchange,提问作者landa
相关产品推荐
相关产品推荐

