数据被保留,但@JoinColumn = null

时间:2019-08-28 10:32:02

标签: sql spring hibernate spring-data-jpa

我正在尝试执行简单的插入。有活动,其中包含门票。当我仅保存事件但@JoinColumn不会生成ID时,将同时保存事件和票证。看起来像这样:

事件表 enter image description here

门票表: enter image description here

有人可以告诉我这里发生了什么吗?我认为映射是正确的。

基本实体:

@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;
    }

2 个答案:

答案 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