Rached Anis
Rached Anis

Reputation: 349

Hibernate Mapping OneToMany + inheritance

I'm asking to know the best way to map between my orders and requests. The Order class is:

@Entity
@Table(name = "Orders")
public class Order {

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

}

I have a class that takes an Order attribute

@Entity
@Table(name = "Requests")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="request_type",discriminatorType=DiscriminatorType.STRING)
public class Request {

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

@ManyToOne(targetEntity = Order.class, fetch = FetchType.EAGER)
@JoinColumn(name = "oldOrder_id", referencedColumnName = "id")
private Order oldOrder;
}

I have this subclass of Request which takes another Order attribute

@Entity
@DiscriminatorValue("Edit")
public class EditRequest extends Request {

@ManyToOne(targetEntity = Order.class, fetch = FetchType.EAGER)
@JoinColumn(name = "newOrder_id", referencedColumnName = "id")
private Order newOrder;
}

And I have another subclass (CancelRequest) of Request which doesnt take an Order attribute.

It doesn't make sense if in the Order class I put :

@OneToMany(mappedBy="oldOrder")
private Collection<Request> requests;

@OneToMany(mappedBy="newOrder")
private Collection<EditRequest> editRequests;

Because an order should have only one attribute of Type Collection<Request>.

So What should I put in my Order class?

Upvotes: 1

Views: 2070

Answers (1)

xperjon
xperjon

Reputation: 46

First make an interface for Request

public interface Request {

   public Long getId();

   public Order getNewOrder();

   public Order getOldorder();
}

Then make an abstract super class for holding the inheritance annotations and id field.

@Entity
@Table(name = "Requests")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="request_type",discriminatorType=DiscriminatorType.STRING)
public class AbstractRequest {

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

Then make two imlpementing classes: EditRequest and CancelRequest

@Entity
@DiscriminatorValue("Edit")
public class EditRequest extends AbstractRequest implements Request {

   @ManyToOne(targetEntity = Order.class, fetch =FetchType.EAGER)
   private Order newOrder;

   @ManyToOne(targetEntity = Order.class, fetch =FetchType.EAGER)
   private Order oldOrder;

   public Order getNewOrder() {
      return neworder;
   }

   public Order getOldOrder() {
      return oldOrder;
   }
}

@Entity
@DiscriminatorValue("Cancel")
public class CancelRequest extends AbstractRequest implements Request {

   public Order getNewOrder() {
      return null;
   }

   public Order getOldOrder() {
      return null;
   }
}

Then you could just reference the interface from the Order class with the AbstractRequest class as target entity.

@OneToMany(mappedBy="order" targetEntity = AbstractRequest.class, fetch = FetchType.EAGER)
private Collection<Request> requests;

Upvotes: 2

Related Questions