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 查询,您必须使用createQuery
(createNativeQuery
用于 SQL 查询);
@Table(name=...)
将定义数据库中表的名称,但不会在您编写 JPQL 查询时定义。为此,您可以使用@Entity(name="...")
。在你的情况下,它应该是@Entity(name="TableA")
;
查询的返回值是两个字段,不是TableAEntity
。所以将其作为参数传递给createQuery
是错误的;
返回a.id
和b.id
很奇怪。如果需要实体,可以返回a
和b
。
如果TableA
和TableB
之间存在关联,例如:
@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;
);
如果TableA
和TableB
之间没有关联:
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];
...
);
请注意,您可以更改选择并混合使用这两种方法。
但是因为TableAEntity
和TableBEntity
之间存在关联,所以您可以将这一切重写为:
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列的主要内容,如果未能解决你的问题,请参考以下文章
sQL数据库表的主键列设为标识,增量为1,下次插入数据时能不插入主键列吗