Farr
Farr

Reputation: 31

Change name of foreign key constraint in One-to-Many unidirectional relation in Hibernate

I'm using Hibernate version 5.2.10.

Here is my relation in Order entity:

@Entity
public class Order {

  @Id
  @Column(name = "ID", length = 22)
  private String id;

  @OneToMany(mappedBy = "orderId", cascade = CascadeType.ALL, orphanRemoval = true)
  private List<OrderLine> lines;

}

And in OrderLine I have:

@Entity
public class OrderLine {

  @Id
  @Column(name = "ID", length = 22)
  private String id;

  @Column(name = "ORDER_ID", nullable = false, length = 22)
  private String orderId;

}

All is working just fine, but now I want to change the name of the database FK constraint, so:

Order (now I use @JoinColumn instead of "mappedBy"):

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "ORDER_ID", foreignKey = @ForeignKey(name = "FKNAME"))
private List<OrderLine> lines;

OrderLine:

@Column(name = "ORDER_ID", nullable = false, length = 22)
private String orderId;

In this situation I have a problem when deleting an Order, because Hibernate sets the orderId to null before deleting the Order and the OrderLines, violating the not null orderId constraint.

To avoid this, I have to remove the nullable = false (but I do not want!).

Is there a solution? Can I change the name of the database FK constraint while using the "mappedBy"?

EDIT

As primary key identifier, I use a UUID version 4 (random) base64 encoded. After removing the padding chars, it is exactly 22 chars long. The ID is generated and assigned at construction time of any entity. But this is not related to my problem.

Upvotes: 3

Views: 4684

Answers (3)

Farr
Farr

Reputation: 31

I ended up doing what I wouldn't, I removed the nullable=false constraint in OrderLine.orderId and I added an assertion into my code to ensure that no one can set orderId to null.

Upvotes: 0

wypieprz
wypieprz

Reputation: 8219

The following approach seems to work:

@Entity
public class Orders {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    @Column(name = "ORDER_ID", length = 36)
    private String idc;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "ORDER_ID", foreignKey = @ForeignKey(name = "FK_NAME"))
    private List<OrderLine> lines;

    ...
}

@Entity
public class OrderLine {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    @Column(name = "ORDERLINE_ID", nullable = false, length = 36)
    private String orderlineId;
    ...
}

I have used Hibernate auto-generated UUIDs but idea is same as yours. The database schema is:

ORDERS                      ORDERLINE
------------                ----------------
ORDER_ID  PK --+            ORDERLINE_ID  PK
               +--FK_NAME-- ORDER_ID      FK

Removing orders works too.


UPDATE: a few operations on the entities

OrderLine ol1 = new OrderLine();
OrderLine ol2 = new OrderLine();
OrderLine o13 = new OrderLine();
OrderLine ol4 = new OrderLine();
OrderLine ol5 = new OrderLine();
OrderLine ol6 = new OrderLine();
Orders o1 = new Orders(Arrays.asList(ol1));
Orders o2 = new Orders(Arrays.asList(ol2, o13));
Orders o3 = new Orders(Arrays.asList(ol4, ol5, ol6));

em.begin();
em.persist(o1);
em.persist(o2);
em.persist(o3);
em.commit();

em.begin();
Orders o = p.provider().find(Orders.class, id);
em.remove(o);
em.commit();

Upvotes: 4

Phạm Quốc Bảo
Phạm Quốc Bảo

Reputation: 894

In Order, it should be @onetomany and mappedBy orderline_id. In Orderline, you should @manytoone and add @joincolumn with name ID..

Upvotes: 0

Related Questions