java – Hibernate和Thymeleaf无限递归
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – Hibernate和Thymeleaf无限递归,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4171字,纯文字阅读大概需要6分钟。
内容图文
我有2个类,其中一个属性映射为OneToMany / ManyToOne关系.问题是,当我执行select并传递给te视图时,我想用Thymeleaf将对象解析为javascript,但它循环关系的无限原因.
我的课程:
班级成员:
@Entity
@Table(name = "player")
public class Player {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@Column(name = "level")
private int level;
@Column(name = "experience")
private int experience;
@OneToMany(mappedBy="player", cascade = CascadeType.ALL)
private List<InventoryItem> inventory;
// Constructor
public Player() {
}
// Getters & Setters...
}
类InventoryItem:
@Entity
@Table(name = "inventory_item")
public class InventoryItem {
@Id
@GeneratedValue
@Column(name = "id")
private int id;
@ManyToOne
@JoinColumn(name="id_player")
private Player player;
public InventoryItem() {
}
//Getters and Setters...
}
然后我将Player对象传递给视图,并使用javascript将console.log传递给它:
<script th:inline="javascript">
/*<![CDATA[*/
console.log([[${player}]]);
/*]]>*/
</script>
这是错误:
如何在解析为javascript时阻止双向关系,比如忽略所有InventoryItems中的Player atrubute?
解决方法:
我今天遇到了这个问题,我猜Thymeleaf并没有为此提供简单的解决方案.在将它传递给Thymeleaf之前,您始终可以将对父项的引用设置为null,但这看起来有点难看.
调查Thymeleaf的源代码,我注意到它使用Introspector来获取有关属性的信息,因此我们可以通过实现BeanInfo来隐藏一些属性.最简单的方法是在bean的同一个包上创建一个类,并在名称后附加BeanInfo.您可以扩展SimpleBeanInfo并仅实现您感兴趣的方法(在本例中为getPropertyDescriptors).
在您的示例中,您可以:
public class InventoryItemBeanInfo extends SimpleBeanInfo {
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor id = new PropertyDescriptor("id", InventoryItem.class);
PropertyDescriptor[] descriptors = {id};
return descriptors;
} catch (IntrospectionException e) {
throw new Error(e.toString());
}
}
}
这样,Thymeleaf就不会看到你的Player属性了,你就不会再有无限递归了.
此解决方案的缺点是您必须记住,每次更改InventoryItem bean的属性时,都必须转到BeanInfo并向其添加新属性.
所以我提出了另一个解决方案.它有点复杂,但一旦设置它就更容易维护.
我们首先创建一个注释来指示应该隐藏属性.我们称之为HiddenProperty:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HiddenProperty {}
现在我们实现一个泛型BeanInfo类,它将使用反射检查bean并找到属性.我们还将检查是否存在我们的注释,当它出现时我们忽略该方法:
public class HiddenPropertyAwareBeanInfo extends SimpleBeanInfo {
private Class<?> beanClass;
private PropertyDescriptor[] descriptors;
public HiddenPropertyAwareBeanInfo(Class<?> beanClass) {
this.beanClass = beanClass;
}
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
if(descriptors != null) {
return descriptors;
}
Method[] methodList = beanClass.getMethods();
List<PropertyDescriptor> propDescriptors = new ArrayList<>();
for(Method m : methodList) {
if(Modifier.isStatic(m.getModifiers())) {
continue;
}
try {
if(m.getParameterCount() == 0 && !m.isAnnotationPresent(HiddenProperty.class)) {
if(m.getName().startsWith("get")) {
propDescriptors.add(new PropertyDescriptor(m.getName().substring(3), beanClass));
} else if(m.getName().startsWith("is")) {
propDescriptors.add(new PropertyDescriptor(m.getName().substring(2), beanClass));
}
}
} catch(IntrospectionException ex) {
continue;
}
}
descriptors = new PropertyDescriptor[propDescriptors.size()];
return propDescriptors.toArray(descriptors);
}
}
现在,创建扩展此类的BeanInfo:
public class InventoryItemBeanInfo extends HiddenPropertyAwareBeanInfo {
public InventoryItemBeanInfo() {
super(InventoryItem.class);
}
}
最后,注释要隐藏的属性的getter:
@Entity
@Table(name = "inventory_item")
public class InventoryItem {
@Id
@GeneratedValue
@Column(name = "id")
private int id;
@ManyToOne
@JoinColumn(name="id_player")
private Player player;
public InventoryItem() {
}
@HiddenProperty
public Player getPlayer() {
return this.player;
}
//Other getters and setters...
}
你有它.现在,您可以根据需要更改您的属性,并且Thymeleaf不会看到您的Player属性.
关于这个解决方案的一个重要的事情是,它不是100%符合Java Beans规范,它不考虑索引属性和其他一些细节的存在.您可以查看Introspector的source code,了解它们如何提取此信息并改进此解决方案.
但是,就个人而言,我认为这应该在Thymeleaf中修复. Thymeleaf是一个非常优雅的工具,不得不采用这种解决方法让我有点伤心.
内容总结
以上是互联网集市为您收集整理的java – Hibernate和Thymeleaf无限递归全部内容,希望文章能够帮你解决java – Hibernate和Thymeleaf无限递归所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。