我有以下情况:
public class ContrivedEntity extends Model {
private Long id;
private Shipper shipper;
private Location location;
}
public class Shipper extends Model {
private Long id;
private Country country;
}
ContrivedEntity有几种关系,它的关系本身也有依赖关系...... 我创建了一个功能,用户可以搜索Contrived Entities ....这个搜索功能不需要加载依赖项,但是当我使用play的帮助器Json.toJson序列化结果时,它会延迟加载其他依赖项,导致几个其他疑问......
我已设法通过使用Jackson Views(在最终结果中我想忽略的实体中使用注释)来阻止此行为... 但是我正在寻找可以在Ebean结束时完成的事情......同时撰写EBean查询......
以这种方式可以防止延迟加载吗? 如果回答“否”,那么Hibernate会提供这样的功能吗? 任何帮助都会非常感激... 如果您需要更多上下文,请留下评论,我将编辑问题。
非常感谢
答案 0 :(得分:3)
我认为您可以使用Ebean的PathProperties和JSON支持来完全按照您的意愿执行操作。 Ebean内置了良好的JSON支持,这也是它的原因之一。
也就是说,您可以使用PathProperties定义希望包含在JSON输出和查询中的属性。在当前的Ebean中,您使用Query.apply(pathProperties)...来告诉查询要获取的对象图的哪一部分。
一个例子:
PathProperties pathProperties =
PathProperties.parse("(id,status,name,shippingAddress(id,line1,city),billingAddress(*),contacts(*))");
List<Customer> customers = Ebean.find(Customer.class)
.apply(pathProperties)
.findList();
String jsonString = Ebean.json().toJson(customers, pathProperties);
System.out.println(jsonString);
请注意,Ebean现在内部使用了Jackson核心,因为它内置了JSON支持,并且github中还有一个Jackson Ebean模块,但尚未发布。
将杰克逊的观点映射到Ebean&#39; pathProperties&#39;但我还没有看过那个。
希望这会有所帮助 干杯,罗布。
答案 1 :(得分:1)
...但是我正在寻找可以在Ebean结束时完成的事情......同时编写Ebean查询......
这是不可能的,很多人会喜欢这个功能(我2),唯一合理的方法是创建专用的模型类并使用所选数据“手动”填充它。
同样使用反射是一种很好的方法,特别是如果你有许多不同情况的高级REST api。
答案 2 :(得分:1)
只是添加一个额外的选择。 Ebean的查询现在还支持禁用延迟加载。
query.setDisableLazyLoading(true)
所以目前有3个选项:
我可能会喜欢第四种选择,但需要时间/精力。
答案 3 :(得分:0)
我试图找到像......一样简单的东西。
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate4Module());
Json.setObjectMapper(mapper);
https://github.com/FasterXML/jackson-datatype-hibernate
感谢您的帮助
答案 4 :(得分:0)
我需要一个解决方案,以避免在Json.toJson序列化期间ebean延迟加载并想出了这个。它非常多毛,但它具有本地化到模型类的优点,并且可以与标准的Json.toJson一起使用。
定义通用助手:
/**
* Check if a lazy-loaded property on an ebean model class has been loaded without accidentally loading it
* @param clazz The class instance of the object to check (T.class)
* @param bean The actual object to check the property on
* @param propertyName The name of the property to check
* @param <T> The class of the object
* @return Whether it has already been loaded or not
*/
public static <T> boolean isPropertyLoaded(Class<T> clazz, T bean, String propertyName) {
// avoid ebean lazy loading by using the secret ebean api
if (bean instanceof EntityBean) {
// obtain the ebean descriptor of the class and property
BeanDescriptor<T> beanDescriptor = ((SpiEbeanServer) Oracle.getCurrent()).getBeanDescriptor(clazz);
BeanProperty property = beanDescriptor.getBeanProperty(propertyName);
EntityBean eb = (EntityBean) bean;
EntityBeanIntercept ebi = eb._ebean_getIntercept();
// is this the simple case?
if (!ebi.isLoadedProperty(property.getPropertyIndex())) return false;
// if it is a list, check if it is populated
Object value = property.getValue(eb);
if (value instanceof BeanList) {
BeanList list = (BeanList) value;
// if it is marked as loaded and is not null
return list.isPopulated();
}
}
return true;
}
然后在ebean模型类中,使用它:
@JsonIgnore
@ManyToMany(fetch=LAZY)
@JoinTable(...)
public List<RelatedEntity> relatedEntities;
// getter used during JSON serialize to avoid ebean lazy loading
@JsonProperty("relatedEntities")
@JsonInclude(JsonInclude.Include.NON_NULL)
public List<RelatedEntity> getJsonRelatedEntities() {
if (Helper.isPropertyLoaded(ThisEntity.class, this, "relatedEntities")) {
return relatedEntities;
} else {
return null;
}
}