问题描述
我有这样的查询。我通过学生ID我需要学生以及他们的父母的一些领域以及父母的一些领域 - >地址[这里是我面临的主要问题]我正在使用 AliasToBeanNestedResultTransformer 转换器通过
这里是它的实现
$
public List< Student> searchForStudent(Integer studentId)
{
Projection p = Projections.projectionList()。create()
.add(Projections.property(name),name)//它的学生名称OK
.add (Projections.property(lastname),lastname)//它的学生名称OK
.add(Projections.property(age),age)//学生AGE它工作正常
.add(Projections.property(p.phone),parent.phone)//它的父母电话工作正常
.add(Projections.property(address.state)。as(parent .Address.state)); //我需要一个来自address.state的字段,这里是问题...
Session session = ......
Criteria like = session.createCriteria(Student.class).add(prepareForSelect( ))//一些过滤器..
.createAlias(parent,p)//学生的父母。学生有一个父母
.createAlias(parent.Address,地址)//父母的地址......父母有一个地址。
.setProjection(p)
.setResultTransformer(new AliasToBeanNestedResultTransformer(Student.class));
List< Student> results = like.list();
返回结果;
}
抛出
<$在线程main中的异常org.hibernate.PropertyAccessException:在调用com.generic.model.Parent.Address的setter时发生IllegalArgumentException
pre>
FYI是一些类型不匹配,我在 SAMI 代码中进行了一些跟踪,我看到这个
[MyState]
[地址]
$ b在这种情况下,
$ b
似乎Hibernate正在返回一个字符串状态 MyState 使用地址对象,这是类型不匹配。
我已经改进了SamiAndoni类,也许它解决了您的问题。
package com.alutiiq.develop.promanagesys.core .util;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import org.hibernate.transform.ResultTransformer;
/ **
*使用嵌套alises变换alises的帮助
*
* @author Miguel Resendiz
*
* /
public class AliasToBeanNestedResultTransformer extends
AliasedTupleSubsetResultTransformer {
private static final long serialVersionUID = -8047276133980128266L;
private static final int TUPE_INDEX = 0;
private static final int ALISES_INDEX = 1;
private static final int FIELDNAME_INDEX = 2;
private static final PropertyAccessor accessor = PropertyAccessorFactory
.getPropertyAccessor(property);
private final Class<?> resultClass;
private Object [] entityTuples;
private String [] entityAliases;
私人地图< String,Class<>> fieldToClass = new HashMap< String,Class<>>();
私人地图< String,List<>> subEntities = new HashMap< String,List<>>();
私人列表< String> nestedAliases = new ArrayList< String>();
私人地图< String,Class<>> listFields = new HashMap< String,Class<>>();
$ b $ public boolean isTransformedValueATupleElement(String [] aliases,
int tupleLength){
return false;
}
public AliasToBeanNestedResultTransformer(Class<?> resultClass){
this.resultClass = resultClass;
public Object transformTuple(Object [] tuple,String []别名){
handleSubEntities(tuple,aliases);
cleanParams(元组,别名);
ResultTransformer rootTransformer = new AliasToBeanResultTransformer(
resultClass);
Object root = rootTransformer.transformTuple(entityTuples,
entityAliases);
loadSubEntities(root);
cleanMaps();
返回root;
}
private void handleSubEntities(Object [] tuple,String []别名)
抛出HibernateException {
String fieldName =;
String aliasName =;
尝试{
for(int i = 0; i< aliases.length; i ++){
String alias = aliases [i];
if(alias.contains(。)){
String [] sp = alias.split(\\\。);
StringBuilder aliasBuilder = new StringBuilder();
for(int j = 0; j if(j == 0){
fieldName = sp [j];
} else {
aliasBuilder.append(sp [j]);
aliasBuilder.append(。);
}
}
aliasName = aliasBuilder.substring(0,
aliasBuilder.length() - 1);
nestedAliases.add(别名);
manageEntities(fieldName,aliasName,tuple [i]);
}
}
} catch(NoSuchFieldException e){
throw new HibernateException(无法实例化resultclass:
+ resultClass.getName()+for field名称:+ fieldName
+和别名:+ aliasName);
}
}
private Class<?> findClass(String fieldName)抛出NoSuchFieldException,
SecurityException {$ b $ if(fieldToClass.containsKey(fieldName)){
return fieldToClass.get(fieldName);
} else {
Class<?> subclass = resultClass.getDeclaredField(fieldName)
.getType();
if(subclass.equals(List.class)|| subclass.equals(Set.class)){
if(subclass.equals(List.class)){
listFields.put(fieldName,LinkedList.class);
} else {
listFields.put(fieldName,HashSet.class);
}
Field field = resultClass.getDeclaredField(fieldName);
ParameterizedType genericType =(ParameterizedType)字段
.getGenericType();
subclass =(Class<>)genericType.getActualTypeArguments()[0];
}
fieldToClass.put(fieldName,subclass);
返回子类;
$ b @SuppressWarnings(unchecked)
private void manageEntities(String fieldName,String aliasName,
Object tupleValue)throws NoSuchFieldException,SecurityException {
Class<?> subclass = findClass(fieldName);
if(!subEntities.containsKey(fieldName)){
List< Object> list = new ArrayList< Object>();
list.add(new ArrayList< Object>());
list.add(new ArrayList< String>());
list.add(FIELDNAME_INDEX,子类);
subEntities.put(fieldName,list); $(b
((List< Object>)subEntities.get(fieldName).get(TUPE_INDEX))
.add(tupleValue);
((List< String>)subEntities.get(fieldName).get(ALISES_INDEX))
.add(aliasName);
$ b $ private void cleanParams(Object [] tuple,String [] aliases){
entityTuples = new Object [aliases.length - nestedAliases.size()];
entityAliases = new String [aliases.length - nestedAliases.size()];
for(int j = 0,i = 0; j if(!nestedAliases.contains(aliases [j])){
entityTuples [i] = tuple [j];
entityAliases [i] =别名[j];
++ i;
$ @SuppressWarnings({unchecked,rawtypes})
private void loadSubEntities(Object root)throws HibernateException {
尝试{
for(String fieldName:subEntities.keySet()){
Class<?> subclass =(Class<> subEntities.get(fieldName).get(
FIELDNAME_INDEX);
ResultTransformer subclassTransformer = new AliasToBeanNestedResultTransformer(
subclass);
Object subObject = subclassTransformer.transformTuple(
((List< Object>)subEntities.get(fieldName).get(0))
.toArray(),
((List< Object>)subEntities.get(fieldName).get(1))
.toArray(new String [0]));
Setter setter = accessor.getSetter(resultClass,fieldName);
if(listFields.containsKey(fieldName)){
Class<?> collectionClass = listFields.get(fieldName);
Collection subObjectList =(Collection)collectionClass
.newInstance();
subObjectList.add(subObject);
setter.set(root,subObjectList,null);
} else {
setter.set(root,subObject,null);
$ b $ catch(Exception e){
throw new HibernateException(e);
private void cleanMaps(){
fieldToClass = new HashMap< String,Class<>>();
subEntities = new HashMap< String,List<>>();
nestedAliases = new ArrayList< String>();
listFields = new HashMap< String,Class<>>();
}
}
我希望它对您有所帮助。
--------------编辑07/25/15 ---------------
分组嵌套列表。
public List< ;?扩展实体<>>> cleanList(
List<?extends Entity<>> resultList)throws DataException {
List< Entity<>> entities = new ArrayList< Entity<>>();
实体<?> current = null; (实体<>实体:resultList){
if(entity.getId()== null){
continue;
尝试{
}
}
if(current == null){
current = entity;
继续; (current.getId()。equals(entity.getId())){
append(current,entity);
}
if
} else {
entities.add(current);
current = entity;
if(current!= null){
entities.add(current);
}
cleanSubList(entities);
返回实体;
} catch(Exception e){
throw new DataException(e);
$ b @SuppressWarnings({rawtypes,unchecked})
public Set< ;?扩展实体<>>> cleanList(
Set< ;? extends Entity<>> resultList)抛出DataException {
List listToClean = new LinkedList();
listToClean.addAll(resultList);
listToClean = cleanList(listToClean);
resultList.clear();
resultList.addAll(listToClean);
返回resultList;
}
@SuppressWarnings({unchecked,rawtypes})
private void append(实体<?> current,实体<>下一个)
throws IllegalArgumentException,IllegalAccessException {
Field [] fields = current.getClass()。getDeclaredFields();
for(Field field:fields){
if(field.getType()。equals(List.class)){
field.setAccessible(true);
List valueNext =(List)field.get(next);
List valueCurrent =(List)field.get(current);
if(valueNext!= null){
if(valueCurrent!= null){
valueCurrent.addAll(valueNext);
field.set(current,valueCurrent);
} else {
field.set(current,valueNext);
$ b $ else if(field.getType()。equals(Set.class)){
field.setAccessible(true);
设定值Next =(Set)field.get(next);
Set valueCurrent =(Set)field.get(current);
if(valueNext!= null){
if(valueCurrent!= null){
valueCurrent.addAll(valueNext);
field.set(current,valueCurrent);
} else {
field.set(current,valueNext);
@SuppressWarnings({rawtypes,unchecked})
private void cleanSubList(List< ;? extends Entity<>> listToClean)
throws IllegalArgumentException,IllegalAccessException,
DataException {
for(Entity<> entity:listToClean ){
Field [] fields = entity.getClass()。getDeclaredFields();
for(Field field:fields){
if(field.getType()。equals(List.class)){
field.setAccessible(true);
List valueToClean =(List)field.get(entity);
//抛出一个线程
if(valueToClean!= null){
valueToClean = cleanList(valueToClean);
field.set(entity,valueToClean);
}
} else if(field.getType()。equals(Set.class)){
field.setAccessible(true);
Set valueToClean =(Set)field.get(entity);
//抛出一个线程
if(valueToClean!= null){
valueToClean = cleanList(valueToClean);
field.set(entity,valueToClean);
}
}
}
}
}
为了加速这个过程,我建议在主进程中抛出一个线程。
这是我的实体界面:
package com.alutiiq.develop.promanagesys.common.entity;
import java.io.Serializable;
$ b $ / **
* Hibernate通信实体
*
* @author Miguel Resendiz
*
* @param< I>
*主键类型
* /
public interface实体< I extends Serializable>扩展Serializable {
$ b $ / **
*使用主键来启用poissibility来编写通用查询
*
* @return主键值为实体
* /
我getId();
void setId(I id);
void setId(String id);
使用示例:
criteria.setResultTransformer(new AliasToBeanNestedResultTransformer(
entityClass));
列表< Project> projects = criteria.list();
projects =(List< Project>)cleanList(projects);
i have a query like this. i pass the student ID i need some fields from Student as well as their parent as well some fields from the parent->Address[here is the main problem i am facing] i am using AliasToBeanNestedResultTransformer transformer by Sami Andoni
here is the implementation of it CODE
here is my code.
public List<Student>searchForStudent(Integer studentId) { Projection p=Projections.projectionList().create() .add(Projections.property("name"),"name")//the student name it works O.K .add(Projections.property("lastname"),"lastname")//the student name it works O.K .add(Projections.property("age"),"age")//the student AGE it works O.K .add(Projections.property("p.phone"),"parent.phone")//the parent phone it works O.K .add(Projections.property("address.state").as("parent.Address.state")); // i need a field from address.state here is the problem... Session session = ...... Criteria like = session.createCriteria(Student.class).add(prepareForSelect())//some filters.. .createAlias("parent","p")//the parent of the student. a student have one parent .createAlias("parent.Address","address")//the address of the parent.... a parent have one address. .setProjection(p) .setResultTransformer(new AliasToBeanNestedResultTransformer(Student.class)); List<Student>results=like.list(); return results; }it throws
Exception in thread "main" org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.generic.model.Parent.AddressFYI is some type mismatch i have done some tracing in SAMI code and i see this
[MyState] [Address]seems that Hibernate is returning a String State MyState in this case and the transformer is using a Address Object and this is the type Mismatch.
is any help is hugely needed it
thanks a lot.
解决方案I have improved the SamiAndoni class, maybe it solve your issue
package com.alutiiq.develop.promanagesys.core.util; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.transform.AliasToBeanResultTransformer; import org.hibernate.transform.AliasedTupleSubsetResultTransformer; import org.hibernate.transform.ResultTransformer; /** * Help to transform alises with nested alises * * @author Miguel Resendiz * */ public class AliasToBeanNestedResultTransformer extends AliasedTupleSubsetResultTransformer { private static final long serialVersionUID = -8047276133980128266L; private static final int TUPE_INDEX = 0; private static final int ALISES_INDEX = 1; private static final int FIELDNAME_INDEX = 2; private static final PropertyAccessor accessor = PropertyAccessorFactory .getPropertyAccessor("property"); private final Class<?> resultClass; private Object[] entityTuples; private String[] entityAliases; private Map<String, Class<?>> fieldToClass = new HashMap<String, Class<?>>(); private Map<String, List<?>> subEntities = new HashMap<String, List<?>>(); private List<String> nestedAliases = new ArrayList<String>(); private Map<String, Class<?>> listFields = new HashMap<String, Class<?>>(); public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { return false; } public AliasToBeanNestedResultTransformer(Class<?> resultClass) { this.resultClass = resultClass; } public Object transformTuple(Object[] tuple, String[] aliases) { handleSubEntities(tuple, aliases); cleanParams(tuple, aliases); ResultTransformer rootTransformer = new AliasToBeanResultTransformer( resultClass); Object root = rootTransformer.transformTuple(entityTuples, entityAliases); loadSubEntities(root); cleanMaps(); return root; } private void handleSubEntities(Object[] tuple, String[] aliases) throws HibernateException { String fieldName = ""; String aliasName = ""; try { for (int i = 0; i < aliases.length; i++) { String alias = aliases[i]; if (alias.contains(".")) { String[] sp = alias.split("\\."); StringBuilder aliasBuilder = new StringBuilder(); for (int j = 0; j < sp.length; j++) { if (j == 0) { fieldName = sp[j]; } else { aliasBuilder.append(sp[j]); aliasBuilder.append("."); } } aliasName = aliasBuilder.substring(0, aliasBuilder.length() - 1); nestedAliases.add(alias); manageEntities(fieldName, aliasName, tuple[i]); } } } catch (NoSuchFieldException e) { throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName() + " for field name: " + fieldName + " and alias name:" + aliasName); } } private Class<?> findClass(String fieldName) throws NoSuchFieldException, SecurityException { if (fieldToClass.containsKey(fieldName)) { return fieldToClass.get(fieldName); } else { Class<?> subclass = resultClass.getDeclaredField(fieldName) .getType(); if (subclass.equals(List.class) || subclass.equals(Set.class)) { if (subclass.equals(List.class)) { listFields.put(fieldName, LinkedList.class); } else { listFields.put(fieldName, HashSet.class); } Field field = resultClass.getDeclaredField(fieldName); ParameterizedType genericType = (ParameterizedType) field .getGenericType(); subclass = (Class<?>) genericType.getActualTypeArguments()[0]; } fieldToClass.put(fieldName, subclass); return subclass; } } @SuppressWarnings("unchecked") private void manageEntities(String fieldName, String aliasName, Object tupleValue) throws NoSuchFieldException, SecurityException { Class<?> subclass = findClass(fieldName); if (!subEntities.containsKey(fieldName)) { List<Object> list = new ArrayList<Object>(); list.add(new ArrayList<Object>()); list.add(new ArrayList<String>()); list.add(FIELDNAME_INDEX, subclass); subEntities.put(fieldName, list); } ((List<Object>) subEntities.get(fieldName).get(TUPE_INDEX)) .add(tupleValue); ((List<String>) subEntities.get(fieldName).get(ALISES_INDEX)) .add(aliasName); } private void cleanParams(Object[] tuple, String[] aliases) { entityTuples = new Object[aliases.length - nestedAliases.size()]; entityAliases = new String[aliases.length - nestedAliases.size()]; for (int j = 0, i = 0; j < aliases.length; j++) { if (!nestedAliases.contains(aliases[j])) { entityTuples[i] = tuple[j]; entityAliases[i] = aliases[j]; ++i; } } } @SuppressWarnings({ "unchecked", "rawtypes" }) private void loadSubEntities(Object root) throws HibernateException { try { for (String fieldName : subEntities.keySet()) { Class<?> subclass = (Class<?>) subEntities.get(fieldName).get( FIELDNAME_INDEX); ResultTransformer subclassTransformer = new AliasToBeanNestedResultTransformer( subclass); Object subObject = subclassTransformer.transformTuple( ((List<Object>) subEntities.get(fieldName).get(0)) .toArray(), ((List<Object>) subEntities.get(fieldName).get(1)) .toArray(new String[0])); Setter setter = accessor.getSetter(resultClass, fieldName); if (listFields.containsKey(fieldName)) { Class<?> collectionClass = listFields.get(fieldName); Collection subObjectList = (Collection) collectionClass .newInstance(); subObjectList.add(subObject); setter.set(root, subObjectList, null); } else { setter.set(root, subObject, null); } } } catch (Exception e) { throw new HibernateException(e); } } private void cleanMaps() { fieldToClass = new HashMap<String, Class<?>>(); subEntities = new HashMap<String, List<?>>(); nestedAliases = new ArrayList<String>(); listFields = new HashMap<String, Class<?>>(); } }I hope it help you.
--------------edit 07/25/15---------------
To group nested list.
public List<? extends Entity<?>> cleanList( List<? extends Entity<?>> resultList) throws DataException { List<Entity<?>> entities = new ArrayList<Entity<?>>(); Entity<?> current = null; try { for (Entity<?> entity : resultList) { if (entity.getId() == null) { continue; } if (current == null) { current = entity; continue; } if (current.getId().equals(entity.getId())) { append(current, entity); } else { entities.add(current); current = entity; } } if (current != null) { entities.add(current); } cleanSubList(entities); return entities; } catch (Exception e) { throw new DataException(e); } } @SuppressWarnings({ "rawtypes", "unchecked" }) public Set<? extends Entity<?>> cleanList( Set<? extends Entity<?>> resultList) throws DataException { List listToClean = new LinkedList(); listToClean.addAll(resultList); listToClean = cleanList(listToClean); resultList.clear(); resultList.addAll(listToClean); return resultList; } @SuppressWarnings({ "unchecked", "rawtypes" }) private void append(Entity<?> current, Entity<?> next) throws IllegalArgumentException, IllegalAccessException { Field[] fields = current.getClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(List.class)) { field.setAccessible(true); List valueNext = (List) field.get(next); List valueCurrent = (List) field.get(current); if (valueNext != null) { if (valueCurrent != null) { valueCurrent.addAll(valueNext); field.set(current, valueCurrent); } else { field.set(current, valueNext); } } } else if (field.getType().equals(Set.class)) { field.setAccessible(true); Set valueNext = (Set) field.get(next); Set valueCurrent = (Set) field.get(current); if (valueNext != null) { if (valueCurrent != null) { valueCurrent.addAll(valueNext); field.set(current, valueCurrent); } else { field.set(current, valueNext); } } } } } @SuppressWarnings({ "rawtypes", "unchecked" }) private void cleanSubList(List<? extends Entity<?>> listToClean) throws IllegalArgumentException, IllegalAccessException, DataException { for (Entity<?> entity : listToClean) { Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(List.class)) { field.setAccessible(true); List valueToClean = (List) field.get(entity); // Throw a thread if (valueToClean != null) { valueToClean = cleanList(valueToClean); field.set(entity, valueToClean); } } else if (field.getType().equals(Set.class)) { field.setAccessible(true); Set valueToClean = (Set) field.get(entity); // Throw a thread if (valueToClean != null) { valueToClean = cleanList(valueToClean); field.set(entity, valueToClean); } } } } }To speed up the process I´m suggesting throw a thread in the main process.
This is my Entity interface:
package com.alutiiq.develop.promanagesys.common.entity; import java.io.Serializable; /** * Entity for Hibernate comunications * * @author Miguel Resendiz * * @param <I> * Primary key type */ public interface Entity<I extends Serializable> extends Serializable { /** * Enable poissibility to write generic queries using primary key * * @return primary key value for entity */ I getId(); void setId(I id); void setId(String id); }Usage example:
criteria.setResultTransformer(new AliasToBeanNestedResultTransformer( entityClass)); List<Project> projects = criteria.list(); projects = (List<Project>) cleanList(projects);
这篇关于Java Hibernate Transformer AliasToBeanNestedResultTransformer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!