【发布时间】:2019-08-28 10:32:02
【问题描述】:
我正在尝试执行简单的插入。有事件,它包含门票。当我只保存事件但 @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;
}
请注意,我正在通过 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;
}
【问题讨论】:
-
不要使用仅用于记录内容的
peek。相反,您应该在 y9oureventDTOtoEvent方法中下降addTicket。 -
为什么要使用 .
peek(event -> event.getTickets().forEach(event::addTicket))如果票都准备好绑定到事件,hibernate 会自动设置 id 事件到票 -
你看过生成的SQL语句了吗?
-
删除 peek 也不起作用,我添加了 sql 语句。
-
@MushifAliNawaz 添加了。
标签: sql spring hibernate spring-data-jpa