JPA 映射:一个 table 的主键列到另一个 table 的非 Pk/Fk 列

JPA mapping :Primary key column of one table to non Pk/Fk column of another table

@Entity
@Table(name = "TableA")
public class TableAEntity{
        
        @Id
        @Column(name = "RUL_ID"
        private Integer rulId;
        
        @Column(name = "COMMENT"
        private Integer comment;
        
        @OneToOne
        @JoinColumn(name = "RUL_ID" referencedColumnName ="PRNT_ID", insertable=false, updatable=false)
        private TableBEntity tableB;
  
        //GETTERS AND SETTERS
        
}
        
@Entity
@Table(name = "TableB")
public class TableBEntity{
        
        @Id
        @Column(name = "ADD_ID"
        private Integer addID;
        
        @Column(name = "PRNT_ID"
        private Integer prntId;  
     
        //GETTERS AND SETTERS

}

有 2 个数据库表。

  1. 主键为 rulId 的表 A。
  2. 主键为 addID 的表 B。

我必须使用 JPA 本机查询来实现自定义的 JOIN 查询。

Java代码为:

StringBuilder querySql = "select a.rulId, b.prntId from  TableA a JOIN TableB b ON a.rulID = b.prntId"  
Query tabQuery = entityManager.createNativeQuery(querySql.toString, TableAEntity.class)  
List<TableAEntity> entityList = tabQuery.getResultList(); 

如何建立一对一(TableA:TableB)关系,当它们没有任何键链接时(pk/fk)。 我无法将 ResultList 映射到我的实体 class.Primary TableA“rulId”的键总是链接到 TableB“addId”的主键,其中我想将它关联到“prntId”。

谁能帮忙解决这个问题。

有几点需要注意:

  • 对于 JPA 查询,您必须使用 createQuerycreateNativeQuery 用于 SQL 查询);
  • @Table(name=...) 将在数据库中定义 table 的名称,但在编写 JPQL 查询时不会。为此,您可以使用 @Entity(name="...")。在你的情况下,它应该是 @Entity(name="TableA");
  • 查询的return值是两个字段,不是TableAEntity。所以将它作为参数传递给 createQuery 是错误的;
  • return a.idb.id 很奇怪。如果你想要实体,你可以 return ab.

如果TableATableB之间存在关联,例如:

@Entity(name = "TableA")
public class TableAEntity {
...
        @OneToOne
        @JoinColumn(referencedColumnName ="PRNT_ID", insertable=false, updatable=false)
        public TableBEntity tableB;
}

那么你可以运行下面的查询:

String jpqlQuery = "from TableA a join fetch a.tableB b";
List<TableAEntity> entityList = entityManager.createQuery(jpqlQuery, TableAEntity.class).getResultList()

entityList.foreach( tableAEntity -> {
   TableBEntity tabB = tableAEntity.tableB;
});

如果TableATableB之间没有关联:

String jpqlQuery = "select a, b from TableA a JOIN TableB b ON a.rulID = b.prntId";
List<Object[]> entityList = entityManager.createQuery(jpqlQuery).getResultList()

entityList.foreach( row -> {
   TableAEntity tabA = (TableAEntity) row[0];
   TableBEntity tabB = (TableBEntity) row[1];
});

但如果您真的只需要 ID,这也行得通:

String jpqlQuery = "select a.rulId, b.prntId from  TableA a JOIN TableB b ON a.rulID = b.prntId";
List<Object[]> entityList = entityManager.createQuery(jpqlQuery).getResultList()

entityList.foreach( row -> {
   Integer tabAId = (Integer) row[0];
   Integer tabBId = (Integer) row[1];
   ...
});

请注意,您可以更改 select 并混合使用这两种方法。

但是因为 TableAEntityTableBEntity 之间存在关联,您可以将所有这些重写为:

String jpqlQuery = "from TableA";
List<TableAEntity> entityList = entityManager.createQuery(jpqlQuery, 
TableAEntity.class).getResultList()

entityList.foreach( entity -> {
   TableAEntity tabA = entity;
   TableBEntity tabB = entity.getTableB();
   ...
});

无论有无关联,您都可以从 select 子句中 return 获得您需要的所有值组合:

select a, b.addID from ...
select a, b from ...