我有两个字符串/数字/的POJO ...我想只得到这个pojo,而没有任何可以通过hibernate附加的列表/地图/集中的子POJO。如果我执行查询以获得第一个pojo,当有人触摸那些子对象时抛出异常。
这是正常行为,我同意这一点,但有没有办法,不要称之为:
object.setSomeMap(null);
但要将其设置为默认行为?我不认为将这样的每个属性设置为最佳解决方案,因为我拥有相当大的模型。
谢谢!
答案 0 :(得分:1)
将FetchType
设置为FetchType.LAZY
,从数据库加载类时不会加载它们。我给你举个例子:
@Entity
@Table(name="FOO")
public class Foo{
@Id
@GeneratedValue
@Column
private int id;
@Column
private String prop1;
@Column
private String prop2;
//You don't have to set fetch type like this, as lazy is the default for collections,
//but it doesn't really hurt anything
@OneToMany(fetch=FetchType.LAZY)
private List<Bar> listOfBars;
}
因此,当您加载Foo
课程时,id
,prop1
和prop2
将从数据库加载并设置,但listOfBars
个对象不会填充。
每当您尝试访问listOfBars
对象时,Hibernate会检测到它并尝试填充对象,然后才能获取它。 AFAIK如果您尝试将listOfBars
设置为null,Hibernate将检测到此并尝试删除您的外键,如果更新对象,则有效删除listOfBars
的所有成员。例如:
@Transactional
public Foo doStuffWithFoo(int id){
Foo foo = fooDao.find(id);
//Set listOfBars to null so we can't call it.
//This is bad and will cause disaster when we update Foo.
foo.setListOfBars(null);
//Do some stuff with Foo that changes values.
fooDao.saveOrUpdate(foo);
return foo;
}
因为您在这里将listOfBars
对象设置为null,AFAIK Hibernate将删除所有外键,因为您的列表不再存在。 Hibernate知道列表是空的,因为它在创建对象时没有填充它,而是一个你设置为null / empty的列表。如果是前者的情况,它除了可能在需要时级联更新状态之外什么都不做。对于后者,如果orphanRemoval
设置为true,它将清除您的关联,可能删除Bar对象。
但是,如果您从方法中返回listOfBars
后尝试访问Foo
,则会出现其他问题。出现此问题的原因是,在您尝试访问@Transactional
之前,您最初用于提取Foo
课程的listOfBars
会话已结束。此时您有3个选项,每个选项都有自己的问题。
第一个选项(这是大多数人尝试的,因为它不起作用而感到沮丧)是您可以打开一个新会话,并尝试填充您的listOfBars
对象。 Hibernate假定您的Foo
对象和Bar
中的所有listOfBars
对象都可能在事务结束后发生了变化(这是完全正确的),因此它会引发异常。
另一种选择是再次获取整个Foo
对象 并填充新事务中的listOfBars
对象。这样做的问题是,做这样的多次选择是非常低效的。
您最后的选择是永远不要尝试访问listOfBars
对象,如果您知道它不在那里。您甚至无法执行空检查,因为Hibernate将检测您对getListOfBars()
的调用,并尝试在实际进行空检查之前填充该对象。
我编写了一个Hibernate教程,用于创建对象关系here,您可能会发现它们很有帮助。我还讨论了诸如Lazy vs Eager对象集合以及其他一些Hibernate的东西,它们在设计用于Hibernate的类时会有所帮助。
祝你好运