julianfperez
julianfperez

Reputation: 1744

Aggregation relationship via JPA annotations

I am trying to establish the aggregation relationship between two Java classes through JPA annotations in order to persist them into a database.

enter image description here

public class Ticket 
{
    private String ticketNo;
    private Date releasedDate;
    private boolean printed;
}

public class Discount 
{
    private String percentage;
    private Date releasedDate;
    private boolean printed;
}

Such as mentioned here, the aggregation relationship is unidirectional and thus, only it is necessary to map one side. From the solution given by this page, I think the solution will be:

 public class Discount 
    {
        private String percentage;
        private Date releasedDate;
        private boolean printed;
        @ManyToOne(name="TICKET_ID")
        private Ticket ticket;
    }

However, in some examples of aggregation, the many side class appears inside the one side class. Thus, I am considering this too:

 public class Ticket 
        {
            private String ticketNo;
            private Date releasedDate;
            private boolean printed;
            @OneToMany(mappedBy="ticket")
            private List<Discount> discounts = new ArrayList<Discount>();
        }

Which option is the proper one?

Upvotes: 2

Views: 4103

Answers (2)

ujulu
ujulu

Reputation: 3309

This how you map a unidirectional many-to-one relationship:

@Entity
public class Ticket {
    @Id
    @GeneratedValue
    private Long id;

    private String ticketNo;
    private Date releasedDate;
    private boolean printed;

    // getters and setters
}

@Entity
public class Discount {
    @Id
    @GeneratedValue
    private Long id;

    private String percentage;
    private Date releasedDate;
    private boolean printed;

    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "TICKET_ID")  // you can rename the join column 
    private Ticket ticket;

    // getters and setters
}

Note:

  • JoinColumn (foreign key in the database terminology) must be on the many side of the relationship (this is the Discount in your case).
  • The @Id annotations are also mandatory. In this case, the ID will be generated by the persistence provider automatically. If you are using database sequence or table or some other strategy you can redefine it.

Upvotes: 2

dukethrash
dukethrash

Reputation: 1529

That looks right to me. A discount has a ticket. You could also include the discounts accessible from the tickets like ticket.getDiscounts() if you need to access them in a query such as SELECT t FROM Ticket t WHERE t.discounts.percentage >= :discountPercentage.

@Entity
public class Ticket {
    @Id
    private String ticketNo;
    private Date releasedDate;
    private boolean printed;

    @OneToMany(mappedBy = "ticket", fetch = FetchType.LAZY)
    private List<Discounts> discounts;
}

@Entity
public class Discount {
       private String percentage;
       private Date releasedDate;
       private boolean printed;

       @ManytoOne(name="TICKET_ID")
       private Ticket ticket;
}

However, I wouldn't recommend using @OneToMany as this can create problems serializing too much data to JSON if you are returning this as JSON results or just lazily loading too much data by accident. You should always be able to work with just @ManyToOne as an example if you did not put the @OneToMany association query can be SELECT t FROM Discount d INNER JOIN d.ticket t WHERE d.percentage >= :discountPercentage

Upvotes: 2

Related Questions