JPA本地查询中如果只想查询出实体的部分字段,可以通过返回方式为列模式的方法来实现!
首先建表(Oracle):
create table NATIVEENTITY
(
u_id VARCHAR2(255) not null,
u_email VARCHAR2(255),
password VARCHAR2(255),
u_name VARCHAR2(255)
)
首先是实体的定义
package com.test.jpa;
import javax.persistence.Column;
import javax.persistence.ColumnResult;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
@NamedNativeQueries({
@NamedNativeQuery(
name = "getNativeEntity",
query = "select u_id,u_name,u_email from NativeEntity",
resultSetMapping = "ReturnColumnEntityList"
)
})
@SqlResultSetMappings({
@SqlResultSetMapping(
name = "ReturnColumnEntityList",
entities = {},
columns = {
@ColumnResult(name = "u_id"),
@ColumnResult(name = "u_name"),
@ColumnResult(name = "u_email")
}
)
})
@Entity
public class NativeEntity {
private String tid;
private String username;
private String password;
private String email;
public NativeEntity() {
}
public NativeEntity(String tid, String username) {
super();
this.tid = tid;
this.username = username;
}
public NativeEntity(String tid, String username, String email) {
super();
this.tid = tid;
this.username = username;
this.email = email;
}
@Column(name = "u_email")
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
@Id
@Column(name="u_id")
@GeneratedValue
public String getTid() {
return tid;
}
@Column(name="u_name")
public String getUsername() {
return username;
}
public void setEmail(String email) {
this.email = email;
}
@Column
public void setPassword(String password) {
this.password = password;
}
public void setTid(String tid) {
this.tid = tid;
}
public void setUsername(String username) {
this.username = username;
}
}
接下来是查询
package com.test.jpa;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class NativeSql {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("manager1");
EntityManager entityManager = factory.createEntityManager();
Query query = entityManager.createNamedQuery("getNativeEntity");
List<Object[]> list = (List<Object[]>)query.getResultList();
List<NativeEntity> neList = castEntity(list, NativeEntity.class);
for(NativeEntity ne : neList){
System.out.println(ne.getTid() + ":" + ne.getUsername());
}
// persistEntity(factory, entityManager);
}
/**
* 通用实体转换方法,将JPA返回的数组转化成对应的实体集合,这里通过泛型和反射实现
* @param <T>
* @param list
* @param clazz 需要转化后的类型
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
private static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz) throws Exception {
List<T> returnList = new ArrayList<T>();
Object[] co = list.get(0);
Class[] c2 = new Class[co.length];
//确定构造方法
for(int i = 0; i < co.length; i++){
c2[i] = co[i].getClass();
}
for(Object[] o : list){
Constructor<T> constructor = clazz.getConstructor(c2);
returnList.add(constructor.newInstance(o));
}
return returnList;
}
/**
* 保存实体
* @param factory
* @param entityManager
*/
@SuppressWarnings("unused")
private static void persistEntity(EntityManagerFactory factory,
EntityManager entityManager) {
entityManager.getTransaction().begin();
NativeEntity ne = new NativeEntity();
ne.setUsername("lisi");
ne.setPassword("3344");
ne.setEmail("liuyong_0204@hotmail.com");
entityManager.persist(ne);
entityManager.getTransaction().commit();
entityManager.close();
factory.close();
}
}
需要注意的几个点是:
1:需要查询的字段必须有相对应的构造方法,并且要一一对应,
比如说:
@ColumnResult(name = "u_id"),
@ColumnResult(name = "u_name"),
@ColumnResult(name = "u_email")
对应的构造方法必须是
public NativeEntity(String tid, String username, String email) {
super();
this.tid = tid;
this.username = username;
this.email = email;
}
顺序不能改变!!!!!!
2:如果@SqlResultSetMappings中使用的返回模式为实体,是不能查询出实体的部分字段!必须指定全部实体字段……太恶心了!