JPA查询实体部分字段
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")})})@Entitypublic 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")@GeneratedValuepublic String getTid() {return tid;}@Column(name="u_name")public String getUsername() {return username;}public void setEmail(String email) {this.email = email;}@Columnpublic 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中使用的返回模式为实体,是不能查询出实体的部分字段!必须指定全部实体字段……太恶心了!