我在我的项目中使用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类?
在上面的回答中,我尝试了很多事情。SQLmapper不知道该把它放在哪里。非托管pojo只是一个问题。我尝试了各种方法,其中一个简单的方法就是像往常一样。我使用的是hibernate-jpa-2.1。
List<TestInfo> testInfoList = factory.createNativeQuery(QueryConstants.RUNNING_TEST_INFO_QUERY)
.getResultList();
唯一需要注意的是POJO具有与查询相同的成员变量名(均为小写)。显然,我甚至不需要像在JPQL中使用TypedQueries那样告诉目标类和查询。
TestInfo.class
@Setter
@Getter
@NoArgsConstructor
@ToString
public class TestInfo {
private String emailid;
private Long testcount;
public TestInfo(String emailId, Long testCount) {
super();
this.emailid = emailId;
this.testcount = testCount;
}
}
首先声明以下注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultEntity {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultColumn {
int index();
}
然后按以下方式注释你的POJO:
@NativeQueryResultEntity
public class ClassX {
@NativeQueryResultColumn(index=0)
private String a;
@NativeQueryResultColumn(index=1)
private String b;
}
然后写注释处理器:
public class NativeQueryResultsMapper {
private static Logger log = LoggerFactory.getLogger(NativeQueryResultsMapper.class);
public static <T> List<T> map(List<Object[]> objectArrayList, Class<T> genericType) {
List<T> ret = new ArrayList<T>();
List<Field> mappingFields = getNativeQueryResultColumnAnnotatedFields(genericType);
try {
for (Object[] objectArr : objectArrayList) {
T t = genericType.newInstance();
for (int i = 0; i < objectArr.length; i++) {
BeanUtils.setProperty(t, mappingFields.get(i).getName(), objectArr[i]);
}
ret.add(t);
}
} catch (InstantiationException ie) {
log.debug("Cannot instantiate: ", ie);
ret.clear();
} catch (IllegalAccessException iae) {
log.debug("Illegal access: ", iae);
ret.clear();
} catch (InvocationTargetException ite) {
log.debug("Cannot invoke method: ", ite);
ret.clear();
}
return ret;
}
// Get ordered list of fields
private static <T> List<Field> getNativeQueryResultColumnAnnotatedFields(Class<T> genericType) {
Field[] fields = genericType.getDeclaredFields();
List<Field> orderedFields = Arrays.asList(new Field[fields.length]);
for (int i = 0; i < fields.length; i++) {
if (fields[i].isAnnotationPresent(NativeQueryResultColumn.class)) {
NativeQueryResultColumn nqrc = fields[i].getAnnotation(NativeQueryResultColumn.class);
orderedFields.set(nqrc.index(), fields[i]);
}
}
return orderedFields;
}
}
使用上述框架如下:
String sql = "select a,b from x order by a";
Query q = entityManager.createNativeQuery(sql);
List<ClassX> results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);
使用DTO设计模式。它在EJB 2.0中使用。实体由容器管理。采用DTO设计模式来解决这一问题。
但是,当应用程序分别开发服务器端和客户端时,现在可能会使用它。DTO用于服务器端不想将带有注释的实体传递/返回给客户端。
DTO示例:
PersonEntity.java
@Entity
public class PersonEntity {
@Id
private String id;
private String address;
public PersonEntity(){
}
public PersonEntity(String id, String address) {
this.id = id;
this.address = address;
}
//getter and setter
}
PersonDTO.java
public class PersonDTO {
private String id;
private String address;
public PersonDTO() {
}
public PersonDTO(String id, String address) {
this.id = id;
this.address = address;
}
//getter and setter
}
DTOBuilder.java
public class DTOBuilder() {
public static PersonDTO buildPersonDTO(PersonEntity person) {
return new PersonDTO(person.getId(). person.getAddress());
}
}
java <——可能需要
public class EntityBuilder() {
public static PersonEntity buildPersonEntity(PersonDTO person) {
return new PersonEntity(person.getId(). person.getAddress());
}
}