我在我的项目中使用JPA .
我来到一个查询,我需要在五个表上进行连接操作 . 所以我创建了一个返回五个字段的本机查询 .
现在我想将结果对象转换为包含相同五个字符串的java POJO类 .
在JPA中是否有任何方法可以直接将该结果转换为POJO对象列表?
我来到以下解决方案..
@NamedNativeQueries({
@NamedNativeQuery(
name = "nativeSQL",
query = "SELECT * FROM Actors",
resultClass = db.Actor.class),
@NamedNativeQuery(
name = "nativeSQL2",
query = "SELECT COUNT(*) FROM Actors",
resultClass = XXXXX) // <--------------- problem
})
现在在resultClass中,我们是否需要提供一个实际的JPA实体类?或者我们可以将它转换为包含相同列名的任何JAVA POJO类?
11 回答
如果您使用的是Spring,则可以使用
org.springframework.jdbc.core.RowMapper
这是一个例子:
请参阅下面的示例,将POJO用作伪实体,以便在不使用复杂的SqlResultSetMapping的情况下从本机查询中检索结果 . 在你的POJO中只需要两个注释,一个裸@Enity和一个虚拟@Id . @Id可用于您选择的任何字段,@ Id字段可以有重复键但不能为空值 .
由于@Enity不映射到任何物理表,因此该POJO称为伪实体 .
环境:eclipselink 2.5.0-RC1,jpa-2.1.0,mysql-connector-java-5.1.14
你可以下载完整的maven项目here
本机查询基于mysql示例员工db http://dev.mysql.com/doc/employee/en/employees-installation.html
persistence.xml中
Employee.java
EmployeeNativeQuery.java
将SQL查询转换为POJO类集合的简单方法,
我找到了几个解决方案 .
Using Mapped Entities (JPA 2.0)
使用JPA 2.0无法将本机查询映射到POJO,它只能通过实体完成 .
例如:
但在这种情况下,
Jedi
必须是映射的实体类 .在此处避免未经检查的警告的替代方法是使用命名的本机查询 . 因此,如果我们在实体中声明本机查询
然后,我们可以简单地做:
这更安全,但我们仍然限制使用映射实体 .
Manual Mapping
我尝试了一些解决方案(在JPA 2.1到来之前)使用一些反射来对POJO构造函数进行映射 .
此方法基本上采用元组数组(由本机查询返回),并通过查找具有相同字段数和相同类型的构造函数将其映射到提供的POJO类 .
然后我们可以使用方便的方法,如:
我们可以简单地使用这种技术如下:
JPA 2.1 with @SqlResultSetMapping
随着JPA 2.1的到来,我们可以使用@SqlResultSetMapping注释来解决问题 .
我们需要在实体的某处声明一个结果集映射:
然后我们简单地做:
当然,在这种情况下,
Jedi
不需要是映射的实体 . 它可以是常规的POJO .Using XML Mapping
我是其中一个发现在我的实体中添加所有这些非常具有侵入性的东西之一,我特别不喜欢实体中命名查询的定义,所以或者我在
META-INF/orm.xml
文件中做了所有这些:这些都是我所知道的解决方案 . 如果我们可以使用JPA 2.1,最后两个是理想的方式 .
首先声明以下注释:
然后按如下方式注释您的POJO:
然后编写注释处理器:
使用以上框架如下:
使用
DTO Design Pattern
. 它用于EJB 2.0
. 实体是容器管理的 .DTO Design Pattern
用于解决此问题 . 但是,当应用程序分别开发Server Side
和Client Side
时,它现在可能会被使用 .DTO
在Server side
不希望将带注释的Entity
传递/返回Client Side
时使用 .DTO示例:
PersonEntity.java
PersonDTO.java
DTOBuilder.java
EntityBuilder.java < - 它是需要的
JPA提供SqlResultSetMapping,允许您将原始查询的任何返回映射到实体或自定义类 .
EDIT JPA 1.0不允许映射到非实体类 . 仅在JPA 2.1中添加了ConstructorResult以将返回值映射到java类 .
另外,对于OP的计数问题,应该足以用单个ColumnResult定义结果集映射 .
如果你使用
Spring-jpa
,这是答案和这个问题的补充 . 如果有任何缺陷请更正 . 我主要使用三种方法根据我遇到的实际需要实现“映射结果Object[]
到pojo”:JPA内置方法就足够了 .
JPA内置方法是不够的,但定制
sql
及其Entity
就足够了 .前2失败了,我必须使用
nativeQuery
. 以下是示例 . pojo期望:Method 1 :将pojo更改为界面:
和存储库:
Method 2 :存储库:
注意:POJO构造函数的参数序列在POJO定义和sql中必须相同 .
Method 3 :在
Entity
中使用@SqlResultSetMapping
和@NamedNativeQuery
作为Edwin Dalorzo的例子回答 .前两种方法会调用许多中间处理程序,如自定义转换器 . 例如,
AntiStealing
定义secretKey
,在它被持久化之前,插入一个转换器来加密它 . 这将导致前2个方法返回转换后的secretKey
,这不是我想要的 . 虽然方法3将克服转换器,并且返回secretKey
将与存储的相同(加密的) .是的,使用JPA 2.1很容易 . 你有非常有用的注释 . 它们简化了你的生活 .
首先声明您的本机查询,然后是结果集映射(定义数据库返回到POJO的数据的映射) . 写下你的POJO课程(为简洁起见,不包括在内) . 最后但并非最不重要的:在DAO中创建一个方法(例如)来调用查询 . 这对我来说是一个dropwizard(1.0.0)应用程序 .
首先在实体类中声明本机查询:
在下面,您可以添加结果集映射声明:
稍后在DAO中,您可以将查询称为
而已 .
可以执行展开过程以将结果分配给非实体(即Beans / POJO) . 程序如下 .
用法适用于JPA-Hibernate实现 .
由于其他人已经提到了所有可能的解决方案,我正在分享我的解决方案 .
在
Postgres 9.4
的情况下,在使用Jackson
时,我相信你可以找到其他数据库 .
另外,仅供参考,JPA 2.0 native query results as map