JPA / Hibernate:同一连接列上

时间:2017-10-25 10:43:02

标签: java sql hibernate jpa

我很高兴这个社区存在,过去曾多次帮助我解决不同的小问题。 但现在我有一个更大的问题,花了将近两天的时间来寻找答案和解决方案,但不幸的是,我一无所获。 也许有人可以提供帮助并且之前遇到过类似的问题。

我会试着解释一下: 我想用项目构建一种树结构。 一个项目可以有多个子项目(例如文章(父项)及其成分(儿童))。这些子物品可以再生几个孩子等等。但是一个项目也可以有一个或多个过程(例如烹饪)。进程不需要像项目那样处于树结构中。 所以我构建了一个模型,它包含表Item,表ItemResource和表Process。每个表都有一个复合主键。表ItemResource应该是其他表的连接表,因此它将保留对父项的引用和对具体项的引用或对进程的引用。 因此它在PK中有一个属性resourceType,因此我们可以看到它是项目的资源还是要处理的资源。 我的方法(代码)看起来像这样:

@Entity 
@Table(name="Item")
public class Item 
{

    @Getter @Setter
    @EmbeddedId
    private ItemIdPK id;

    @Getter @Setter
    @Column(name="name", length=50)
    @Size(max=50)
    private String name;


    @Getter @Setter
    @OneToMany(mappedBy = "parentItem")
    private List<ItemResource> itemResources = new ArrayList<ItemResource>();

}

@Embeddable
public class ItemIdPK implements Serializable 
{

    public ItemIdPK() {

    }

    public ItemIdPK(String itemNumber, short mandator) {
        this.itemNumber = itemNumber;
        this.mandator = mandator;
    }

    @Getter @Setter
    @Column(name="itemNumber", length=31)
    @Size(max=31)
    private String itemNumber;

    @Getter @Setter
    @Column(name="mandator")
    @Size(max=2)
    private short mandator;

}



@Entity
@Table(name="ItemResource")
public class ItemResource 
{   

    @Getter @Setter
    @EmbeddedId
    private ItemResourceIdPK id;

    @Getter @Setter
    @Column(name="quantity")
    private BigDecimal quantity;    //extra column in join table


    @Getter @Setter
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "refItemNumber", referencedColumnName="itemNumber", insertable = false, updatable = false),
        @JoinColumn(name = "mandator", referencedColumnName="mandator", insertable = false, updatable = false)
    })
    private Item parentItem;


    @Getter @Setter
    @OneToOne
    @JoinColumns({
        @JoinColumn(name = "resourceNumber", referencedColumnName="itemNumber", insertable = false, updatable = false),
        @JoinColumn(name = "mandator", referencedColumnName="mandator", insertable = false, updatable = false)
    })
    private Item item;


    @Getter @Setter
    @OneToOne
    @JoinColumns({
        @JoinColumn(name = "resourceNumber", referencedColumnName="processNumber", insertable = false, updatable = false),
        @JoinColumn(name = "mandator", referencedColumnName="mandator", insertable = false, updatable = false)
    })
    private Process process;

}

@Embeddable
public class ItemResourceIdPK implements Serializable 
{

    public ItemResourceIdPK() {

    }

    public ItemResourceIdPK(String resourceNumber, short mandator, String refItemNumber, ResourceType resourceType) {
        this.resourceNumber = resourceNumber;
        this.mandator = mandator;
        this.refItemNumber = refItemNumber;
        this.resourceType = resourceType;
    }

    @Getter @Setter
    @Column(name="refItemNumber", length=31)    // --> reference for parent item
    @Size(max=31)
    private String refItemNumber;

    @Getter @Setter
    @Column(name="resourceNumber", length=31)       // --> itemNumber or processNumber
    @Size(max=31)
    private String resourceNumber;

    @Getter @Setter
    @Column(name="mandator")
    @Size(max=2)
    private short mandator;

    @Getter @Setter
    @Column(name="resourceType", length=3)
    @Enumerated(EnumType.STRING)
    private ResourceType resourceType;


    public enum ResourceType {
        MA,     //first type (for items)
        AG;     //second type (for processes)

        public String value() {
            return name();
        }

        public static ResourceType fromValue(String v) {
            return valueOf(v);
        }
    }
}


@Entity
@Table(name="Process")
public class Process 
{

    @Getter @Setter
    @EmbeddedId
    private ProcessIdPK id;

    @Getter @Setter
    @Column(name="processName", length=50)
    @Size(max=50)
    private String processName;


    public Process() {

    }

    public Process(String processName) {
        super();
        this.processName = processName;
    }
}

@Embeddable
public class ProcessIdPK implements Serializable 
{   
    public ProcessIdPK() {

    }

    public ProcessIdPK(String processNumber, short mandator) {
        this.processNumber = processNumber;
        this.mandator = mandator;
    }

    @Getter @Setter
    @Column(name="processNumber", length=31)
    @Size(max=31)
    private String processNumber;

    @Getter @Setter
    @Column(name="mandator")
    @Size(max=2)
    private short mandator;

}

问题/结果: ddl自动生成在数据库中做得很好,除了ItemResource表中的两个外键约束,它们避免插入集合,如果在Item表或进程表中没有resourceNumber Id,即使我有不同的resourceType在PK中它们不同。 第二个问题是,在使用某些数据进行测试时,即使我只想加载项目(我认为是因为热切的加载),也有一个实体未找到表格的异常。 但是我怎样才能避免这些问题呢? JPA不可能吗?因为从数据库的逻辑方面来看,它必须是好的。 我能改变什么?数据库模型由客户提供,不应更改。

先致谢谢,并致以诚挚的问候, Bergerjung

P.S。:抱歉,也许这不是一个真正的JPA问题,除了不需要的外键约束,我可以在生成后删除,然后将自动更新设置为false。 也许它只是一个加载问题,并且有任何解决方案(资源类型条件为急切加载(因为OneToOne)进程或项目)。这有什么东西吗?

0 个答案:

没有答案