【问题标题】:Hibernate One to One mapping issue - Cascade feature not working休眠一对一映射问题 - 级联功能不起作用
【发布时间】:2017-09-17 06:25:27
【问题描述】:

我有以下 HBM 实体类:

  1. Train.java、Ticket.java、Booking.java、Passenger.java

我在 Booking 和 Ticket 之间有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 功能。

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    在双向关系中,您应该有从每一方到另一方的参考,您错过了在预订中注入车票,火车也是如此。

    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")
    

    【讨论】:

    • @SumitGhosh 立即查看
    • 不。我认为级联存在一些问题。我已按照您的建议进行了所有更改,但仍然出现相同的错误
    • @SumitGhosh 我认为错误与火车的约束有关,与火车建立关系与预订有相同的问题,我编辑了我的答案,但您需要考虑我提到的所有要点
    【解决方案2】:

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

    【讨论】:

    • 这绝对不是真的。正如 Amer Qarabsa 回答的那样,您需要在坚持之前设置双方。或者,您也可以删除 BOOKING_ID 上的非空约束。在这种情况下,hibernate 将首先将其添加为 NULL,然后更新它
    猜你喜欢
    • 2016-12-31
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 2019-07-14
    • 2015-07-22
    • 1970-01-01
    • 2014-05-12
    相关资源
    最近更新 更多