【问题标题】:Java hibernate/jpa how to create dynamic generic entity that is self relatedJava hibernate/jpa 如何创建自相关的动态通用实体
【发布时间】:2015-01-22 03:26:14
【问题描述】:

我想使用 JPA/hibernate 创建动态和通用的超类,该超类将针对每个层次结构模型进行扩展,例如:角色、页面、目录、部门、权限、树。 我想使用递归和java反射创建这个对象动态树

它应该是这样的:

该实体应该引用自身实体。

我希望它是完全抽象的并且没有数据库表。只有扩展实体应该有 db。

我已经尝试过实现这一目标。但是失败了这么久。 Here is my post about it

我考虑解决方案:

  • @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
  • @Any 和 @AnyMetaDef 映射
  • @MappedSuperclass
  • @Embeddable 和 @Embedded

希望有人给点建议。

【问题讨论】:

  • 在我所有的应用程序中,我曾经这样做过。将公共实体扩展到每个孩子并使用该实体。
  • 你能更精确一点吗?你能给我更多的细节吗?最简单的代码?

标签: java hibernate recursion tree annotations


【解决方案1】:

我想出了以下设计。也可以在GitHub查看:

@MappedSuperclass
public abstract class GenericHierarchicalDictionary {

    public abstract GenericHierarchicalDictionary getParent();

    public abstract Set<? extends GenericHierarchicalDictionary> getChildren();

}

@Entity
@Table(name = "LocalFolder")
public class LocalFolder extends GenericHierarchicalDictionary {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private LocalFolder parent;

    @OneToMany(mappedBy = "parent")
    private Set<LocalFolder> children = new HashSet<LocalFolder>();

    @Override
    public LocalFolder getParent() {
        return parent;
    }

    @Override
    public Set<LocalFolder> getChildren() {
        return children;
    }

    public void addChild(LocalFolder localFolder) {
        localFolder.parent = this;
        children.add(localFolder);
    }
}

@Entity
@Table(name = "RemoteFolder")
public class RemoteFolder extends GenericHierarchicalDictionary {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private RemoteFolder parent;

    @OneToMany(mappedBy = "parent")
    private Set<RemoteFolder> children = new HashSet<RemoteFolder>();

    @Override
    public RemoteFolder getParent() {
        return parent;
    }

    @Override
    public Set<RemoteFolder> getChildren() {
        return children;
    }

    public void addChild(RemoteFolder localFolder) {
        localFolder.parent = this;
        children.add(localFolder);
    }
}

这是测试:

@Test
public void testTree() {
    LOGGER.debug("testAddWebResource");
    doInTransaction(new TransactionCallable<Void>() {
        @Override
        public Void execute(Session session) {
            LocalFolder rootLocalFolder = new LocalFolder();
            session.persist(rootLocalFolder);
            LocalFolder localFolder1 = new LocalFolder();
            rootLocalFolder.addChild(localFolder1);
            session.persist(localFolder1);
            LocalFolder localFolder11 = new LocalFolder();
            localFolder1.addChild(localFolder11);
            session.persist(localFolder11);

            RemoteFolder rootRemoteFolder = new RemoteFolder();
            session.persist(rootRemoteFolder);
            RemoteFolder remoteFolder1 = new RemoteFolder();
            rootRemoteFolder.addChild(remoteFolder1);
            session.persist(remoteFolder1);
            RemoteFolder remoteFolder11 = new RemoteFolder();
            remoteFolder1.addChild(remoteFolder11);
            session.persist(remoteFolder11);
            return null;
        }
    });
}

【讨论】:

  • 我已经检查了您的解决方案。很好。但我想将所有常用方法(如 (getParent(),addChild()))放在抽象方法中:GenericHierarchicalDictionary。当我将这些方法和参数放到GenericHierarchicalDictionary 时,我收到一个错误:rg.hibernate.AnnotationException: @OneToOne or @ManyToOne on models.LocalFolder.parent references an unknown entity: models.GenericHierarchicalDictionary
  • 谢谢。好吧,Hibernate 有其局限性,这就是为什么您必须在实际实现类中显式声明依赖项的原因。总而言之,继承对于行为比重用数据结构更有意义。
  • 好的。因此,让我们在像 LocalFolder 这样的具体类中声明数据结构。但是我们可以将获取父母、孩子、树结构的方法移动到抽象方法中(使用反射吗?)?我试图像许多其他人一样制作通用 DAO,但从未在 GenericDao 中看到该数据结构
  • GenericHierarchicalDictionary 定义了 getParent 和 getChildren。所以基类定义了合同,这意味着你不要;'必须使用反射。您也可以在基类中定义 addChild、setParent。
  • 如何在抽象基类中为这个方法声明主体?
猜你喜欢
  • 1970-01-01
  • 2011-06-23
  • 2019-11-27
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 2019-03-02
相关资源
最近更新 更多