Hibernate一对一映射问题 - 级联功能无法正常工作

时间:2017-09-17 06:25:27

标签: java spring hibernate

我有以下HBM实体类:

  1. Train.java,Ticket.java,Booking.java,Passenger.java
  2. 我在预订和机票之间有One-to-One的关系。 请在下面找到hibernate pojo类:

    @Entity
    @Table(name = "TICKET_MASTER")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Ticket implements Serializable {
    
    @Transient
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "TICKET_SEQ")
    @SequenceGenerator(name = "TICKET_SEQ", sequenceName = "TICKET_SEQ",  allocationSize = 1)
    @Column(name = "TICKET_ID", nullable = false)
    private Long ticketId;
    
    @Column(name = "TICKET_NO", nullable = false)
    private String ticketNo;
    
    @OneToOne(mappedBy = "ticket",cascade=CascadeType.ALL)
    private Booking booking;
    
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "ticket")
    private Set<Passenger> passengers;
    
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "TRAIN_ID", nullable = false)
    private Train train;
    
    //getters & setters
     }
    
    @Entity
    @Table(name = "BOOKING_MASTER")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Booking extends RMSEntity {
        private static final long serialVersionUID = 1L;
    
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO, generator = "BOOKING_SEQ")
      @SequenceGenerator(name = "BOOKING_SEQ", sequenceName = "BOOKING_SEQ", allocationSize = 1)
      @Column(name = "BOOKING_ID", nullable = false)
      private Long bookingId;
    
      @Column(name = "BOOKING_NO", nullable = false)
      private String bookingNo;
    
      @OneToOne
      @JoinColumn(name = "TICKET_ID", referencedColumnName = "TICKET_ID")
      private Ticket ticket;
    
      //gettres & setters
     }
    

    由于问题发生在上述两个班级之间,我省略了乘客和火车的pojo课程。

    请在下面找到我的服务层代码:

    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { Throwable.class })
    @Override
    public void saveBookingDetails(PassengerDTO passengerDTO) {
        BeanUtils.copyProperties(passengerDTO, passenger);*/
        Train train = getDaoProvider().getTrainDao().find(passengerDTO.getTrainId());
        Ticket ticket = new Ticket();
        ticket.setTicketId((long) (Math.random() * 100));
        String ticketNo = UUID.randomUUID().toString().split("-")[0];
        ticket.setTicketNo(ticketNo);
        Booking booking = new Booking();
        String bookingNo = UUID.randomUUID().toString().split("-")[0];
        booking.setBookingId((long)(Math.random() * 100)); 
        booking.setBookingNo(bookingNo); 
        ticket.setBooking(booking); 
        ticket.setTrain(train); 
        getDaoProvider().getTicketDao().saveOrUpdate(ticket);
       }
    

    我遇到以下异常:

    Caused By: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:119)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:97)
    Truncated. see log file for complete stacktrace
    Caused By: java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("SYSTEM"."TICKET_MASTER"."BOOKING_ID")
    
    at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:12296)
    at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:246)
    at weblogic.jdbc.wrapper.PreparedStatement.executeBatch(PreparedStatement.java:197)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:110)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:97)
    Truncated. see log file for complete stacktrace
    

    我正在使用Spring-Hibernate ORM功能。

2 个答案:

答案 0 :(得分:1)

mappedBy表示关系的这一方无法访问级联(操纵数据)关系对象,因为它不是所有者实体。 如果您想要对该实体进行级联,那么您应该将其作为所有者,因此您可以删除mappedBy参数并在@JoinColumn下添加@OneToOne(cascade = CascadeType.All

答案 1 :(得分:0)

在双向关系中,您应该从每一方到另一方都有参考,您错过了在预订中注册的机票,同样适用于火车。

Booking booking = new Booking();
booking.setTicket(ticket);
train.setTicket(ticket);
String bookingNo = UUID.randomUUID().toString().split("-")[0];

另一件事,因为您在预订中的ID是自动生成的,您不应该设置id,hibernate将负责在持久性上为其分配id

String bookingNo = UUID.randomUUID().toString().split("-")[0];// this line should be removed
booking.setBookingId((long)(Math.random() * 100));//this line should be removed
ticket.setTicketId((long) (Math.random() * 100));//this line should be removed

同时删除Ticket的行设置ID。

此外,由于您正在使用序列生成,因此需要将序列指定为序列而不是自动

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOOKING_SEQ")