Reputation: 1204
I have two entities, Event
(it's movie in cinema actually) and Ticket
.
@Entity
public class Event {
@Id
@GeneratedValue
private Integer id;
@OneToOne
private Movie movie;
@Embedded
private Auditorium auditorium;
private LocalDateTime startDateTime;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "event")
private List<Ticket> tickets = new ArrayList<>();
// getters/setters, etc.
Event
contains list of Ticket
's to sell, and every Ticket
should point to exactly one Event
.
@Entity
public class Ticket {
@Id
@GeneratedValue
private Integer id;
@ManyToOne(cascade = CascadeType.ALL, targetEntity = Event.class)
private Event event;
@OneToOne
private User user;
@Embedded
private Seat seat;
private TicketState state;
private Float price;
// getters/setters, etc.
I have EventService
with such a method (Auditorium
contains only amount of seats and numbers of VIP seats), bookingDao
just save Ticket
in DB:
@Override
@Transactional
public boolean assignAuditorium(Integer eventId, Auditorium auditorium, LocalDateTime datetime) {
for (Event event : getAll()) {
if (auditorium.equals(event.getAuditorium()) && intersectsWithAnotherEvent(event, datetime)) {
return false;
}
}
Event currentEvent = getById(eventId);
currentEvent.setAuditorium(auditorium);
currentEvent.setStartDateTime(datetime);
List<Ticket> tickets = currentEvent.getTickets();
Integer seatsNumber = auditorium.getSeatsNumber();
List<Integer> vipSeats = auditorium.getVipSeats();
for (int i = 1; i <= seatsNumber; i++) {
Ticket ticket = new Ticket();
ticket.setEvent(currentEvent);
ticket.setState(TicketState.FREE);
ticket.setSeat(new Seat(i, vipSeats.contains(i) ? SeatStatus.VIP : SeatStatus.STANDARD));
bookingDao.create(ticket);
tickets.add(ticket);
}
return true;
}
}
The problem is: after creation of, f.e. 10 Ticket
's (according to amount of seats in Auditorium
) I have 10 (!!!) identical Event
's as a result of eventService.getAll()
with list of Ticket
's of size 10, each ticket has proper Event
(as expected), instead of one Event
.
So, how to map these entities properly to have one-event-to-many-tickets? Thank you!
UPDATE Implementation of getAll()
@Override
@Transactional
public List<Event> getAll() {
return eventDao.getAll();
}
@Override
public List<Event> getAll() {
return sessionFactory.getCurrentSession().createCriteria(Event.class).list();
}
UPDATE2 I have such a picture right after the end of assignAuditorium
method, suppose, then @Transactional
ends to work. Than I'm inside this method getAll()
shows one Event
with list of Ticket
's as expected. Maybe it will help.
Upvotes: 1
Views: 97
Reputation: 692201
That is caused by the EAGER fetch type on your one to many association. My first advice would be to leave it lazy: you really don't want to load the 250 tickets every time you want to get some information about an event. I would probably even avoid the OneToMany association.
But, in order to solve this, you need to use distinct. Either by adding a DistinctRootEntity result transformer to your criteria query or, preferrably, by using a JPQL query instead of a criteria query:
select distinct e from Event e
Upvotes: 2