【问题标题】:JPA, @Transient field and Native Query mappingJPA、@Transient 字段和本机查询映射
【发布时间】:2015-06-08 08:31:48
【问题描述】:

我有这个实体:

@Entity
@Table(name = "entry")
@SqlResultSetMapping(
    name = "viewEntry",
    entities =
    @EntityResult(entityClass = ViewEntry.class,
            fields = {
                    @FieldResult(name="id", column = "id"),
                    @FieldResult(name="guid", column = "guid"),
                    @FieldResult(name="link", column = "link"),
                    @FieldResult(name="descr", column = "descr"),
                    @FieldResult(name="pubDate", column = "pub_date"),
                    @FieldResult(name="read", column = "my_read")
            }
    )
)
public class ViewEntry implements Serializable {
    @Id
    private Integer id;
    private String guid;
    private String link;
    private String descr;
    private Date pubDate;
    @Transient
    private Boolean read;
}

read 字段位于另一个表中,因此我将其设置为瞬态,以防止 JPA 映射错误。要检索实体的内容,我想使用如下所示的本机查询:

select id,guid,link,descr,pub_date,feed_id,user_id,is_read as my_read from entry join user_to_entry ....
-- skipped dynamic part of query

问题是我不知道如何将本机查询映射到我的实体。特别是我不知道 EntityManager 是否会忽略 @Transient 字段。请帮忙。

【问题讨论】:

  • 可能是错字,但您在映射中将列指定为my_read,但在查询中称为is_read
  • 据我了解,column 参数是结果集中的别名,name 参数是字段名称。如果我错了,请纠正我
  • 你是对的,只是原帖中没有as my_read
  • @PredragMaric 我的错误。发布过时的sql。对不起

标签: java jpa nativequery


【解决方案1】:

要映射本机查询的结果,您可以使用 SqlResultSetMapping http://docs.oracle.com/javaee/7/api/javax/persistence/SqlResultSetMapping.html

如果本地查询中的列与属性名称匹配,或者如果它们在实体中使用@Column 映射,则无需映射。

【讨论】:

  • 在这种映射的情况下,瞬态字段是否会被填充值?我之前尝试过,在read 字段中得到了空值。
  • 查看我编辑的问题以查看我尝试使用的 SqlResultSetMapping
  • 瞬态字段@Transient 和瞬态(Java 关键字)将始终被 JPA 忽略!
  • 太糟糕了。我该怎么做才能填写该字段?
  • 在这个过程中出现了一些其他问题,所以我不得不映射我的实体有点不同。关于这个问题,我以使用 query.getResultList() 的数组结果手动创建对象结束。感谢所有参与的人。
【解决方案2】:

您可以在您的实体中使用@SecondaryTable 将字段映射到另一个表中。像这样的:

...
@SecondaryTable(name="user_to_entry", 
        pkJoinColumns=@PrimaryKeyJoinColumn(name="entry_id"))
public class ViewEntry implements Serializable {
    @Id
    private Integer id;
    private String guid;
    private String link;
    private String descr;
    @Column(name="pub_date")
    private Date pubDate;
    @Column(table = "user_to_entry")
    private Boolean read;
}

如果由于某种原因你不能这样做,你可以像这样将原生 SQL 结果映射到实体

em.createNativeQuery("<native SQL>", ViewEntry.class)

但我认为这不会映射瞬态字段(我可能错了,没有测试过)。

第三个选项是使用@SqlResultSetMapping,但我也不确定这是否适用于瞬态字段。以this 为例。

【讨论】:

  • 我不能使用@SecondaryTable,因为它只接受键作为映射列。我试过了。
  • 我现在要做的是:Query query = em.createNativeQuery(sql.toString(), "viewEntry"); 其中viewEntry 是@SqlResultSetMapping 的名称。
  • 我不知道。如果我删除 @Transient 注释 ORM 将无法在表中找到相应的列。也许有办法禁用此检查并允许命名查询映射此字段?
  • 我认为你做不到。所以,为了清楚起见,@Transient 映射到 @SqlResultSetMapping 时没有填充字段?
  • 是的,我检索到的所有对象都为空值。
【解决方案3】:

在最坏的情况下,您可以使用您的连接创建一个视图,并将您的视图映射为普通表。您只需删除 hibernate 将为您创建的新表。

https://www.w3schools.com/sql/sql_view.asp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-25
    • 2019-04-05
    • 1970-01-01
    • 2013-10-09
    • 2016-02-23
    • 2017-01-02
    • 2016-03-20
    相关资源
    最近更新 更多