当关联表是所有一对多关系的一个时,如何实现一对多映射?

时间:2010-01-04 14:18:05

标签: java hibernate orm jpa

一般情况:第一个表代表一个 - ,第二个表代表许多 - 。第三个表用作两者之间的链接。

我的情况:第一张和第二张表是相同的。第三个表用作具有一对多关系的所有表对之间的链接。第三个表有附加字段(String),其中包含有关2个表的信息。

小例子。假设我们有表项目和类别(一个类别 - >许多项目)。要获取具有类别的所有项目,我们需要执行下一个查询:

select project.name, category.name 
from nodeassociation, project, category 
where nodeassociation.association_name='ProjectCategory'
 and nodeassociation.source_id=project.id 
 and nodeassociation.sink_id=category.id

如何通过JPA指定association_name标准?

UPD:如果使用JPA是不可能的,但是hibernate处理它然后就可以了,什么是hibernate解决方案?

5 个答案:

答案 0 :(得分:1)

建议您在association_name列上过滤的数据库中创建多个视图,然后根据这些视图在映射中定义多对多关系,并在代码中强制执行一对多语义。这种具有中间表的情况只能在Hibernate中使用多对多映射进行处理。

答案 1 :(得分:0)

这通常称为qualified association。应使用Map代替List来实现此类关联。在休眠中没有内置的支持。如果你不关心限定符,那么关联就变成了一个可以用hibernate处理的多对多关系。

但在您的情况下,这不是逻辑级别的合格关联。如果我理解的话,一个关联表用于表示实际几个关联:

  • 如果您可以将每个逻辑关联的数据库架构更改为具有表,则问题将消失。
  • 使用数据库视图“模拟”具有单独的表(如David M所建议的)是另一种选择。为每个逻辑关联创建一个视图,并将其映射为多对多。

答案 2 :(得分:0)

另一个工作可能的解决方案是在hibernate中拥有NodeAssociation的多态实体。每种类型的关联将有一个NodeAssociationX实体。然后ProjectNodeAssociation之间存在一对多关联。并且每NodeAssociationX有一对多和相应的表/实体(Category等)。您可以映射私有字段,以便您可以提供在逻辑级别提供正确视图的公共getter / setter。

public List getCategories()
{
     List categories = new ArrayList();
     for( NodeAssociation na : nodeAssociations )
     {
           if( typeof( na ) = NodeAssociationCategory )
           {
                categories.addAll( ((NodeAssociationCategory)na).getCategories() ); 
           }
     }
     return categories;
}

但这很难看。如果可能,请尝试其他解决方案。

答案 3 :(得分:0)

@Entity
public class Category {

    private Integer id;

    @Id
    public Integer getId() {
        return this.id;
    }

    private LinkBetweenOneCategoryAndManyProject linkClass = new  LinkBetweenOneCategoryAndManyProject();

    @OneToOne
    public LinkBetweenOneCategoryAndManyProject getLinkClass() {
        return this.linkClass;
    }

    public void addProject(Project project) {
        getLinkClass().getProjectList().add(project);
    }

    // delegates to LinkClass
    public String getAdditionalProperty() {
        getLinkClass().getAdditionalProperty();
    }

}

现在我们的项目

@Entity
public class Project {

    private Integer id;

    @Id
    public Integer getId() {
        return this.id;
    }

}

现在我们的LinkBetweenOneCategoryAndManyProject类

@Entity
public class LinkBetweenOneCategoryAndManyProject {

    private Integer categoryId;

    private String additionalField;

    List<Project> projectList;

    @Id
    public Integer getCategoryId() {
        return this.categoryId;
    }

    @OneToMany
    public List<Project> getProjectList() {
        return projectList;
    }

    public String additionalProperty() {
        return this.additionalField;
    }

}

因此,如果要检索类别及其项目,请执行以下操作

select distinct c from Category c left join fetch c.linkedClass lc left join fetch lc.projectList

请注意,我认为Category和LinkBetweenOneCategoryAndManyProject之间的关系是OneToOne

的问候,

答案 4 :(得分:0)

我找到了一个适合原生查询的解决方案。

简而言之:

  1. 我为Project和Category制作了简单的映射,没有任何关系(如OneToMany)
  2. 我将字段category添加到项目实体,并将其标记为@Transient
  3. 在ProjectDAO中,我使用本机查询手动将类别插入到项目中。
  4. 关于JPA Native Queriesrelated jboss docs的文章对我来说是一个起点。