jpa中使用 sql查询时,返回结果直接转为实体bean的实现,
需要自定义一个ResultTransformer,如下,
import java.util.Arrays; import org.apache.log4j.Logger; import org.hibernate.HibernateException; import org.hibernate.property.ChainedPropertyAccessor; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.transform.AliasToBeanResultTransformer; /** * @Description : * @Autor : xiongjinpeng jpx_011@163.com * @Date : 2016年3月18日 上午10:05:00 * @version : */ public class SelfResultTransformer extends AliasToBeanResultTransformer{ /** * */ private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(SelfResultTransformer.class); public <T> SelfResultTransformer(Class<T> resultClass) { super(resultClass); if(resultClass == null) { throw new IllegalArgumentException("resultClass cannot be null"); } else { isInitialized = false; this.resultClass = resultClass; return; } } public boolean isTransformedValueATupleElement(String aliases[], int tupleLength) { return false; } public Object transformTuple(Object tuple[], String aliases[]) { Object result; try { if(!isInitialized) initialize(aliases); else check(aliases); result = resultClass.newInstance(); for(int i = 0; i < aliases.length; i++) if(setters[i] != null) setters[i].set(result, tuple[i], null); } catch(InstantiationException e) { throw new HibernateException((new StringBuilder()).append("Could not instantiate resultclass: ").append(resultClass.getName()).toString()); } catch(IllegalAccessException e) { throw new HibernateException((new StringBuilder()).append("Could not instantiate resultclass: ").append(resultClass.getName()).toString()); } return result; } private void initialize(String aliases[]) { PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(new PropertyAccessor[] { PropertyAccessorFactory.getPropertyAccessor(resultClass, null), PropertyAccessorFactory.getPropertyAccessor("field") }); this.aliases = new String[aliases.length]; setters = new Setter[aliases.length]; for(int i = 0; i < aliases.length; i++) { String alias = aliases[i]; if(alias != null) { this.aliases[i] = alias; alias = UnderlineToCamelUtil.underlineToCamel(alias); try { setters[i] = propertyAccessor.getSetter(resultClass, alias); } catch (Exception e) { logger.warn(resultClass+" property "+alias+" not found"); } } } isInitialized = true; } private void check(String aliases[]) { if(!Arrays.equals(aliases, this.aliases)) throw new IllegalStateException((new StringBuilder()).append("aliases are different from what is cached; aliases=").append(Arrays.asList(aliases)).append(" cached=").append(Arrays.asList(this.aliases)).toString()); else return; } public boolean equals(Object o) { if(this == o) return true; if(o == null || getClass() != o.getClass()) return false; SelfResultTransformer that = (SelfResultTransformer)o; if(!resultClass.equals(that.resultClass)) return false; return Arrays.equals(aliases, that.aliases); } public int hashCode() { int result = resultClass.hashCode(); result = 31 * result + (aliases == null ? 0 : Arrays.hashCode(aliases)); return result; } private final Class resultClass; private boolean isInitialized; private String aliases[]; private Setter setters[]; }
下划线转驼峰工具类,
import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Description : * @Autor : xiongjinpeng jpx_011@163.com * @Date : 2016年3月18日 上午10:20:47 * @version : */ public class UnderlineToCamelUtil { public static final char UNDERLINE='_'; public static String camelToUnderline(String param){ if (param==null||"".equals(param.trim())){ return ""; } int len=param.length(); StringBuilder sb=new StringBuilder(len); for (int i = 0; i < len; i++) { char c=param.charAt(i); if (Character.isUpperCase(c)){ sb.append(UNDERLINE); sb.append(Character.toLowerCase(c)); }else{ sb.append(c); } } return sb.toString(); } /** * 下划线转驼峰 * @param param * @return */ public static String underlineToCamel(String param){ if (param==null||"".equals(param.trim())){ return ""; } int len=param.length(); StringBuilder sb=new StringBuilder(len); for (int i = 0; i < len; i++) { char c=param.charAt(i); if (c==UNDERLINE){ if (++i<len){ sb.append(Character.toUpperCase(param.charAt(i))); } }else{ sb.append(c); } } return sb.toString(); } public static String underlineToCamel2(String param){ if (param==null||"".equals(param.trim())){ return ""; } StringBuilder sb=new StringBuilder(param); Matcher mc= Pattern.compile("_").matcher(param); int i=0; while (mc.find()){ int position=mc.end()-(i++); //String.valueOf(Character.toUpperCase(sb.charAt(position))); sb.replace(position-1,position+1,sb.substring(position,position+1).toUpperCase()); } return sb.toString(); } public static void main(String[] args) { System.out.println(underlineToCamel("a_b_c")); System.out.println(underlineToCamel2("a_b_c")); } }
实际调用如下,
private EntityManager em;
public <K> K getObjectBySql(String sql,Object[] params,Class<K> k){ Query query = em.createNativeQuery(sql); if(params!=null){ for(int i=0,len=params.length;i<len;i++){ Object param=params[i]; query.setParameter(i+1, param); } } query.unwrap(SQLQuery.class).setResultTransformer(new SelfResultTransformer(k)); K object =(K) query.getSingleResult(); return object; }
jpa中调用的是hibernate中的代码,所以hibernate的sql查询类似