如何在hibernate中延迟加载多对多集合?

我可以懒惰加载一对多和多对一的关联,但我不能与多对多关联。

我们有一个城市,我们有商人有地址。 商家可以拥有多个地址,多个商家可以拥有相同的地址。

当我们用get获取商家时,

Merchant merchant = (Merchant) hib_session.get(Merchant.class, id); System.out.println(merchant.getName()); 

没关系,在我们遍历它们之前,地址不会加载。

但是当我们加载商家列表时,

 City city = (City) hib_session.get(City.class, city_name); for(Merchant merchant : city.getMerchants()) { System.out.println(merchant.getName()); } 

即使我们没有获取地址,hibernate也会自动加载它们。

这是我的问题的一个例子。

映射:

                   

有任何想法吗 ?

我找到了两个修复程序。 简单的就是进行交易。 如果您在业务方法中启动事务,您将能够在该方法的生命周期内的任何时间懒惰地初始化这些事务。 如果您的事务是容器管理的,那么该方法上的简单@TransactionAttribute(TransactionAttributeType.REQUIRED)就足以实现此目的。 另一种方法是使用Hibernate.initialize(object.getDesiredColletion())这也将获取您的对象,但也需要一个事务。

我的最后一个解决方案是你没有交易。 这个generics方法基本上会得到你的集合并使用setter方法在你的父对象中设置它们。 您可以通过不传入id并一般地获取它来改进此过程,如果您不关心更改java上的安全设置,您可以直接将集合设置为父对象(即使它是私有的),在这种情况下很多这段代码可以减少。

  public Object fetchCollections(Object parent, Long id, Class... childs) { logger.debug("Need to fetch " + (childs.length) + " collections"); String fieldName = ""; String query = ""; for (int i = 0; i < childs.length; i++) { logger.debug("Fetching colletion " + (i + 1) + " of " + (childs.length)); logger.debug("Collection type is " + childs[i].getSimpleName()); fieldName = findFieldName(childs[i], parent.getClass()); if (fieldName == null) { logger.debug("Trying to search with parent class"); logger.debug(parent.getClass().getSuperclass()); fieldName = findFieldName(childs[i], parent.getClass() .getSuperclass()); } logger.debug("Creating query"); query = "from " + childs[i].getSimpleName() + " obj " + "where " + " obj." + fieldName + ".id=" + id; logger.debug("Query= " + query); Set collection = new HashSet(em.createQuery(query).getResultList()); setCollection(parent, collection, fieldName, childs[i]); } return parent; } private String findFieldName(Class parentClass, Class childClass) { String fieldName = null; boolean isCollection = false; logger.debug("Searching for field of type " + childClass.getSimpleName()); for (Field f : parentClass.getDeclaredFields()) { String type = f.getGenericType().toString(); if (f.getType().isInterface() && f.getGenericType().toString().contains("java.util.Set")) { logger.debug("This field is a collection"); isCollection = true; type = type.substring(type.indexOf("<") + 1); type = type.substring(0, type.length() - 1); } if (isCollection) { logger.debug("Field= " + f.getName() + " " + f.getGenericType()); if (type.equals(childClass.getName())) { logger.debug("*****MATCH FOUND"); fieldName = f.getName(); break; } } else { logger.debug("Type=" + f.getType().getName() + " childType=" + childClass.getName()); if (f.getType().getName().equals(childClass.getName())) { logger.debug("*****MATCH FOUND"); fieldName = f.getName(); break; } } } return fieldName; } private void setCollection(Object result, Set collection, String fieldName, Class childClass) { String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); logger.debug("trivial setter is :" + methodName); Class[] args = new Class[] { java.util.Set.class }; // try the trivial case boolean methodFound = false; Method method = null; try { method = result.getClass().getMethod(methodName, args); methodFound = true; } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { logger.debug("Method not found by trivial method"); } if (!methodFound) { FindMethod: for (Method m : result.getClass().getMethods()) { // logger.debug(m.getName()); for (Type t : m.getGenericParameterTypes()) { // logger.debug("\t"+t); String type = t.toString(); type = type.substring(type.indexOf("<") + 1); type = type.substring(0, type.length() - 1); if (type.equals(childClass.getName())) { logger.debug("***Found the Setter Method"); method = m; break FindMethod; } }// end for parameter Types }// end for Methods }// end if invokeMethod(method, result, false, collection); } private void invokeMethod(Method method, Object obj, boolean initialize, Object... args) { try { if (method != null) { if (initialize) Hibernate.initialize(method.invoke(obj, args)); else method.invoke(obj, args); } logger.debug("Method executed successfully"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } 

您可以使用criteria对象来查询和使用FetchMode.EAGER。