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

Posted

技术标签:

【中文标题】JPA映射:一个表的主键列到另一个表的非Pk/Fk列【英文标题】:JPA mapping :Primary key column of one table to non Pk/Fk column of another table 【发布时间】:2021-07-03 16:50:33 【问题描述】:
@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 个数据库表。

    主键为 rulId 的 TableA。 主键为 addID 的 TableB。

我必须使用 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(); 

当它们没有与任何键(pk/fk)链接时,如何建立这种 OneToOne(TableA:TableB) 关系。 我无法将 ResultList 映射到我的实体类。TableA“rulId”的主键始终链接到 TableB“addId”的 PrimaryKey,其中我想将其关联到“prntId”。

谁能帮忙解决这个问题。

【问题讨论】:

TableBEntity 中的OneToOne 关系是否正确?还是和TableAEntity有关系? 道歉... 已更新相同。 TableA 中存在 OneToOne 关系。 【参考方案1】:

有几点需要注意:

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

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

但是因为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子句中返回你需要的所有值组合:

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

【讨论】:

如果我想在 TableA 实体本身中获取表 A 的所有列和表 B 的 1 列,因为它们都有映射,该怎么办。由于在我的实际代码中,表 A 包含大约 15 列,而表 B 仅包含 5 列......所以我要获取的数据是 TableA 15 列 + 2 TableB 列(由 TableA pk 和 TableB 非 pk/fk 连接)也映射每个像 obj[0] 这样的实体字段的列会使代码看起来很乱。 我已经扩展了我的答案。我想现在你已经掌握了你需要的所有信息。

以上是关于JPA映射:一个表的主键列到另一个表的非Pk/Fk列的主要内容,如果未能解决你的问题,请参考以下文章

父表的主键是子表的主键,如何使用jpa进行映射?

sQL数据库表的主键列设为标识,增量为1,下次插入数据时能不插入主键列吗

如何通过phoenix中查看表的主键信息

JPA / Hibernate:创建一个主键,它是另一个表的主键

学习Spring-Data-Jpa---JPA基本注解

在 JPA 中检索通用实体的主键列定义