Hibernate 通过单个列而不是复合主键进行联接

Hibernate 通过单个列而不是复合主键进行联接,hibernate,exception,jpa,one-to-many,joincolumn,Hibernate,Exception,Jpa,One To Many,Joincolumn,我有一个JPA实体,我想在这个表上添加自连接。这张桌子看起来像 @Entity @Table(name = "TABLE_A") @IdClass(TableAPk.class) public class TableA implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "COLUMN_1", nullable = false, l

我有一个JPA实体,我想在这个表上添加自连接。这张桌子看起来像

@Entity
@Table(name = "TABLE_A")
@IdClass(TableAPk.class)
public class TableA implements Serializable {

    private static final long serialVersionUID = 1L;


    @Id
    @Column(name = "COLUMN_1", nullable = false, length = 64)
    private String            column_1;

    @Id
    @Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
    private BigDecimal        column_2;


    @ManyToOne
    @JoinColumn(name = "COLUMN_1", insertable = false, updatable = false)
    //@ManyToOne(optional = true, fetch = FetchType.LAZY)
    //@JoinTable(name = "KEY_MAPPING", 
    //        joinColumns = { @JoinColumn(name = "J_COLUMN_1", referencedColumnName = "COLUMN_1", insertable = false, updatable = false) } )
    private TableA tableA;

    @OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
    private Set<TableA> tableASet;
根据我的业务逻辑,我只需要在单个列上添加自连接

final Join<TableA, TableA> joinASelf = joinX.join("tableA", JoinType.INNER);
生成的列名显示为“表A\U列2”。我不知道为什么。有线索吗

  • 正确的方法是(不是OP想要的)
  • 您可以使用
    @JoinColumns
    注释(注意复数而不是单数),从而连接:

    @Entity
    @Table(name = "TABLE_A")
    @IdClass(TableAPk.class)
    public class TableA implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
    
        @Id
        @Column(name = "COLUMN_1", nullable = false, length = 64)
        private String            column1;
    
        @Id
        @Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
        private BigDecimal        column2;
    
    
        @ManyToOne
        @JoinColumns({
            @JoinColumn(name = "FK_COL1", referencedColumnName="COLUMN_1"),
            @JoinColumn(name = "FK_COL2", referencedColumnName="COLUMN_2")
        })
        private TableA tableA;
    
        @OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
        private Set<TableA> tableASet;
    

    @JoinColumns有什么问题吗?我的业务逻辑是,在同一个查询中,我想找到TableA中所有具有列_1特定值的行。你不能添加“一列上的自连接”,因为你需要两列来引用该类型的对象,以遵循对象模型。你知道吗?我尝试了许多选项,但在最后的SQL查询中使用了错误的列名。不知道您所指的AssociationOverride是什么。。。它适用于有mappedSuperclass的地方,或者是嵌入类的地方,而您没有这些情况(请参阅JPA规范),正如您所看到的,它无论如何都不起作用。您不能只在一个列上加入,因为您有两个列,正如我在问题中提到的,由于我的业务场景的限制,我只需要在单个列上添加加入。并非所有列都是复合键的一部分。这可以通过使用本机查询实现来实现。我只是想知道为什么不使用JPA。我不能更改DB模式。那不在我手里。我已经在使用JPA2.1了。你能详细说明我该试什么吗?由于我对JPA标准查询不熟悉,您的提示将对我有所帮助。如果您有可能,也请提供有关如何操作的任何现有参考。将
    @ManyToOne
    属性替换为简单的
    私有字符串refCol1
    (您也可以简单地添加它,而不替换任何内容),然后尝试以下JPQL查询:
    选择TableA t1 LEFT JOIN t2 ON t1.column1=t2.refCol1
    ,但请记住:Java类没有正确映射到DB,因为从JPA的角度来看,这不是一种
    多通
    关系(我将从Java中删除它,因为您使用JPA2.1,所以您总是可以编写类似的查询(也可以是标准查询))。好的,我会试试。再一个问题。我不能使用JPQL查询,因为条件和关系是根据搜索条件动态添加的。是否可以使用查询条件尝试相同的操作?嗨,Andrei,我已经编辑了你的答案,以提出最终解决方案的外观。请等待一段时间,直到我被允许向y颁发奖金欧:)
    @ManyToOne
    @AssociationOverride(name="tableA", 
            joinColumns=@JoinColumn(name="COLUMN_1"))
    private TableA tableA;
    
    @Entity
    @Table(name = "TABLE_A")
    @IdClass(TableAPk.class)
    public class TableA implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
    
        @Id
        @Column(name = "COLUMN_1", nullable = false, length = 64)
        private String            column1;
    
        @Id
        @Column(name = "COLUMN_2", nullable = false, precision = 10, scale = 2)
        private BigDecimal        column2;
    
    
        @ManyToOne
        @JoinColumns({
            @JoinColumn(name = "FK_COL1", referencedColumnName="COLUMN_1"),
            @JoinColumn(name = "FK_COL2", referencedColumnName="COLUMN_2")
        })
        private TableA tableA;
    
        @OneToMany(mappedBy="tableA", fetch = FetchType.LAZY)
        private Set<TableA> tableASet;
    
    final CriteriaBuilder criteriaBuilder = entityManagerMds.getCriteriaBuilder();
    // This Pojo is used to fetch only selected fields
    final CriteriaQuery<DummyPojo> createQuery = criteriaBuilder.createQuery(DummyPojo.class);
    
    final Root<TableX> tableX = createQuery.from(TableX.class);
    final Join<TableX, TableA> joinTableA = tableX.join("tableAs", JoinType.INNER);
    
    
    // Every time you want to add a self join, create new root
    final Root<TableA> tableA = createQuery.from(TableA.class);
    final Predicate predicateSelfJoin = criteriaBuilder.equal(joinTableA.<String>get("column_1"), tableA.<String>get("column_1"));