我正在尝试执行简单的插入。有活动,其中包含门票。当我仅保存事件但@JoinColumn
不会生成ID时,将同时保存事件和票证。看起来像这样:
有人可以告诉我这里发生了什么吗?我认为映射是正确的。
基本实体:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Long id;
}
事件实体:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "Event")
@Table(name = "event")
public class Event extends BaseEntity {
private String title;
@Column(columnDefinition = "LONGTEXT")
private String description;
private LocalDate date;
private String img;
@Enumerated(EnumType.STRING)
private MusicGenre genre;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "location_id")
Location location;
@OneToMany(
cascade = CascadeType.ALL,
mappedBy = "event")
Set<Ticket> tickets = new HashSet<>();
public void addTicket(Ticket ticket) {
this.tickets.add(ticket);
ticket.setEvent(this);
}
}
机票实体:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "Ticket")
@Table(name = "ticket")
public class Ticket extends BaseEntity {
@Enumerated(value = EnumType.STRING)
private TicketType type;
private Integer price;
private Integer totalAmmount;
private Integer inStock;
@ManyToOne(
cascade = {
CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH
}
)
@JoinColumn(name = "event_id")
Event event;
}
请注意,我正在通过事件实体中的辅助方法在这些实体之间创建关联。
这是我保存它们的方式:
@Override
@Transactional
public EventsDTO saveAll(EventsDTO eventsDTO) {
return EventsDTO.builder()
.events(
eventsDTO.getEvents().stream()
.map(eventDTO -> eventMapper.eventDTOtoEvent(eventDTO))
.peek(event -> event.getTickets().forEach(event::addTicket))
.map(eventRepository::save)
.map(event -> eventMapper.eventToEventDTO(event))
.collect(Collectors.toList())
).build();
}
此处生成了脚本:
Hibernate: insert into event (date, description, genre, img, location_id, title) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into ticket (event_id, in_stock, price, total_ammount, type) values (?, ?, ?, ?, ?)
Hibernate: insert into ticket (event_id, in_stock, price, total_ammount, type) values (?, ?, ?, ?, ?)
Hibernate: insert into ticket (event_id, in_stock, price, total_ammount, type) values (?, ?, ?, ?, ?)
Hibernate: insert into ticket (event_id, in_stock, price, total_ammount, type) values (?, ?, ?, ?, ?)
Hibernate: insert into ticket (event_id, in_stock, price, total_ammount, type) values (?, ?, ?, ?, ?)
和Mapper实现:
@Override
public Event eventDTOtoEvent(EventDTO eventDTO) {
if ( eventDTO == null ) {
return null;
}
Event event = new Event();
event.setId( eventDTO.getId() );
event.setTitle( eventDTO.getTitle() );
event.setDescription( eventDTO.getDescription() );
event.setDate( eventDTO.getDate() );
event.setImg( eventDTO.getImg() );
event.setGenre( eventDTO.getGenre() );
event.setLocation( locationDTOToLocation( eventDTO.getLocation() ) );
event.setTickets( ticketDTOSetToTicketSet( eventDTO.getTickets() ) );
return event;
}
protected Set<Ticket> ticketDTOSetToTicketSet(Set<TicketDTO> set) {
if ( set == null ) {
return null;
}
Set<Ticket> set1 = new HashSet<Ticket>( Math.max( (int) ( set.size() / .75f ) + 1, 16 ) );
for ( TicketDTO ticketDTO : set ) {
set1.add( ticketDTOToTicket( ticketDTO ) );
}
return set1;
}
protected Ticket ticketDTOToTicket(TicketDTO ticketDTO) {
if ( ticketDTO == null ) {
return null;
}
Ticket ticket = new Ticket();
ticket.setId( ticketDTO.getId() );
ticket.setType( ticketDTO.getType() );
ticket.setPrice( ticketDTO.getPrice() );
ticket.setTotalAmmount( ticketDTO.getTotalAmmount() );
ticket.setInStock( ticketDTO.getInStock() );
ticket.setEvent( eventDTOtoEvent( ticketDTO.getEvent() ) );
return ticket;
}
答案 0 :(得分:1)
您的代码有两个问题。第一个是您映射器中的ticketDTOToTicket()
方法。在下面的语句中:
ticket.setEvent( eventDTOtoEvent( ticketDTO.getEvent() ) );
您正在为每个Event
对象创建一个新的Ticket
对象引用。这与坚持的不同。每个Ticket
对象应引用相同的父Event
对象引用。您应该将父Event
对象引用存储在变量中,然后将相同的引用分配给所有Ticket
对象。
第二个问题是以下行:
.peek(event -> event.getTickets().forEach(event::addTicket))
这里是您在Set<Ticket> tickets
上循环并将它们添加回同一HashSet<>()
的地方:
public void addTicket(Ticket ticket) {
this.tickets.add(ticket);
ticket.setEvent(this);
}
这显然不会做任何事情,因为Set
不会添加重复元素。您应该将其完全删除。
判决:
您的代码的实际问题是每个
Ticket
对象不是 引用相同的父Event
对象引用,而不是每个 它们是指如上所述的不同对象引用。解决此问题 将解决您的问题。
答案 1 :(得分:0)
尝试以下更改:
docker logs
和
@Override
@Transactional
public EventsDTO saveAll(EventsDTO eventsDTO) {
return EventsDTO.builder()
.events(
eventsDTO.getEvents().stream()
.map(eventDTO -> eventMapper.eventDTOtoEvent(eventDTO))
.map(eventRepository::save)
.map(event -> eventMapper.eventToEventDTO(event))
.collect(Collectors.toList())
).build();
}
仅供参考:最好从方法中返回空集合,而不要从@Override
public Event eventDTOtoEvent(EventDTO eventDTO) {
if ( eventDTO == null ) {
return null;
}
Event event = new Event();
event.setId( eventDTO.getId() );
event.setTitle( eventDTO.getTitle() );
event.setDescription( eventDTO.getDescription() );
event.setDate( eventDTO.getDate() );
event.setImg( eventDTO.getImg() );
event.setGenre( eventDTO.getGenre() );
event.setLocation( locationDTOToLocation( eventDTO.getLocation() ) );
event.setTickets( ticketDTOSetToTicketSet( eventDTO.getTickets(), event ) );
return event;
}
protected Set<Ticket> ticketDTOSetToTicketSet(Set<TicketDTO> dtos, Event event) {
if ( dtos == null ) {
return null;
}
return dtos.stream().map(d -> ticketDTOToTicket(d, event)).collect(Collectors.toSet());
}
protected Ticket ticketDTOToTicket(TicketDTO ticketDTO, Event event) {
if ( ticketDTO == null ) {
return null;
}
Ticket ticket = new Ticket();
ticket.setId( ticketDTO.getId() );
ticket.setType( ticketDTO.getType() );
ticket.setPrice( ticketDTO.getPrice() );
ticket.setTotalAmmount( ticketDTO.getTotalAmmount() );
ticket.setInStock( ticketDTO.getInStock() );
ticket.setEvent(event);
return ticket;
}
返回空集合,方法的返回类型为null
。