java hibernate entity:允许通过id和object本身设置相关对象

我有一个以下的Java类,它也是一个Hibernate实体:

@Entity @Table(name = "category") public class Category { @ManyToOne @JoinColumn(name="parent_id") private Category parent; public Category getParent() { return parent; } public void setParent(Category parent) { this.parent = parent; } 

该类别表示类别树中的节点。 我正在实现一个允许CRUD类别的Web服务。 例如,接口能够创建类别树节点,并将类别id作为参数传递。

我只想创建一个新的Category对象并将其持久保存到数据库中而不需要获取父对象。 我的数据提供程序类如下所示:

 public void createCategory(int parent_id, String name, CategoryType type) { Category category = new Category(); category.setName(name); // category.setParent(?); <- I don't have this object here // category.setParentId(id); <- but I do have the id category.setType(type); this.categoryDao.save(category); } 

我的问题是:如果假设我不会调用hibernate来为我取父(这会很愚蠢),我该怎么做才能创建一个带有parent_id集的新Category对象? 我可以为Category类提供setParentId / getParentId方法吗? 它有什么hibernate注释?

Hibernate为这种情况提供了一种称为(相当令人困惑的) Session.load()的方法。

Session.load()返回一个具有给定标识符的惰性代理,而不查询数据库(如果具有给定标识符的对象已经在当前Session加载,则它返回一个对象本身)。

您可以使用该代理初始化要保存的实体中的关系:

 category.setParent(session.load(Category.class, parent_id)); 

请注意,此代码不会检查具有给定id的Category存在性。 但是,如果数据库模式中有外键约束,则在传入无效ID时会出现约束违规错误。

相当于此方法的JPA称为EntityManager.getReference()

还有一个问题的解决方案 – 使用您想要引用的实体的默认构造函数,并设置id和version(如果它是版本化的)。

  Constructor c = entityClass.getDeclaredConstructor(); c.setAccessible(true); S instance = c.newInstance(); Fields.set(instance, "id", entityId.getId()); Fields.set(instance, "version", entityId.getVersion()); return instance; 

我们可以使用这样的方法,因为我们不使用延迟加载,而是具有在GUI上使用的实体的“视图”。 这允许我们摆脱Hibernate用来填充所有渴望关系的所有连接。 视图始终具有实体的ID和版本。 因此,我们可以通过创建一个Hibernate看起来不是瞬态的对象来填充引用。

我尝试了这种方法和session.load()的方法。 他们都工作得很好。 我看到我的方法有一些优点,因为Hibernate不会泄漏其代理中其他地方的代理。 如果没有正确使用,我只会得到NPE而不是’no session bound to thread’exception。

您可以定义延迟初始化

 @ManyToOne(fetch=FetchType.LAZY) 

猜这个列是可空的,所以没有父级(root)保存类别不是问题