2017-02-10 43 views
2

我有两个实体RoomNightBookingCorporateDetails其中BookingCorporateDetails在两列(booking_idroom_night_booking_id)上引用RoomNight。一对一多列外键的断列映射

BookingCorporateDetails是可选的,但RoomNight是强制性的。我试图创建一个外键连接的BookingCorporateDetails表作为 -

AbstractJpaEntity.java

@MappedSuperclass 
@SuppressWarnings("serial") 
public abstract class AbstractJpaEntity implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 

    @Column(name = "created_at") 
    @Temporal(TemporalType.TIMESTAMP) 
    protected Date createdAt; 

    @Column(name = "created_by", length = 32, nullable = true) 
    protected String createdBy; 

    @Column(name = "updated_at") 
    @Temporal(TemporalType.TIMESTAMP) 
    protected Date updatedAt; 

    @Column(name = "updated_by", length = 32, nullable = true) 
    protected String updatedBy; 

    @Column(name = "is_published", columnDefinition = "tinyint(1) default 1") 
    protected boolean isPublished; 

    @Column(name = "is_deleted", columnDefinition = "tinyint(1) default 0") 
    protected boolean isDeleted; 

    // Getters and Setters 
} 

AbstractBookingEntity.java

@MappedSuperclass 
public abstract class AbstractBookingEntity extends AbstractJpaEntity { 

    private static final long serialVersionUID = 6980195228404112444L; 

    @Column(name = "booking_id", nullable = false) 
    protected String bookingId; 

    @Column(name = "room_night_booking_id", nullable = false) 
    protected String roomNightBookingId; 

    public String getBookingId() { 
    return bookingId; 
    } 

    public void setBookingId(String bookingId) { 
    this.bookingId = bookingId; 
    } 

    public String getRoomNightBookingId() { 
    return roomNightBookingId; 
    } 

    public void setRoomNightBookingId(String roomNightBookingId) { 
    this.roomNightBookingId = roomNightBookingId; 
    } 
} 

BookingCorporateDetailsEntity.java

@Entity(name = "booking_corporate_details") 
@Table(name = "booking_corporate_details", uniqueConstraints = { @UniqueConstraint(name = "key_bcd_order_sub_order", columnNames = { "booking_id", "room_night_booking_id" }) }) 
public class BookingCorporateDetailsEntity extends AbstractBookingEntity { 

    private static final long serialVersionUID = -5577224607005257364L; 

    @Column(name = "btc_company") 
    private String billToCompany; 

    @Column(name = "cr_company_name", nullable = false) 
    private String companyName; 

    @Column(name = "cr_manager_name") 
    private String managerName; 

    @Column(name = "cr_manager_email") 
    private String managerEmail; 

    @Column(name = "cr_manager_phone") 
    private String managerPhone; 

    @OneToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinColumns({ 
    @JoinColumn(name = "booking_id", referencedColumnName = "booking_id", insertable = false, updatable = false), 
    @JoinColumn(name = "room_night_booking_id", referencedColumnName = "room_night_booking_id", insertable = false, updatable = false) 
    }) 
    private RoomNightEntity roomNightEntity; 

    public RoomNightEntity getRoomNightEntity() { 
    return roomNightEntity; 
    } 

    public void setRoomNightEntity(RoomNightEntity roomNightEntity) { 
    this.roomNightEntity = roomNightEntity; 
    } 

    // Getters And Setters 
} 

RoomNightEntity.java

@Entity(name = "room_night") 
@Table(name = "room_night", uniqueConstraints = { @UniqueConstraint(name = "key_rm_order_sub_order", columnNames = { "booking_id", "room_night_booking_id" }) }) 
public class RoomNightEntity extends AbstractBookingEntity { 

    private static final long serialVersionUID = 7661960864475909694L; 

    @Column(name = "ota_booking_id", nullable = false) 
    private String otaBookingId; 

    @Column(name = "property_id", nullable = false) 
    private Long propertyId; 

    @Column(name = "room_type_id", nullable = false) 
    private Integer roomTypeId; 

    @Column(name = "booking_status", nullable = false) 
    private Integer bookingStatus; 

    @Column(name = "occupancy", nullable = false) 
    private Integer occupancy; 

    @Column(name = "user_id", nullable = false) 
    private Long userId; 

    @Column(name = "payment_mode", nullable = false) 
    private String paymentMode; 

    @Column(name = "stay_date") 
    @Temporal(TemporalType.DATE) 
    private Date stayDate; 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "roomNightEntity", fetch = FetchType.LAZY) 
    private BookingCorporateDetailsEntity bookingCorporateDetailsEntity; 

    // Getters and Setters 
} 

当我执行的代码,我得到下面的异常 -

java.lang.IllegalStateException: Failed to load ApplicationContext 
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:201) 
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:255) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:111) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:148) 
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) 
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) 
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) 
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) 
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookingEntityManagerFactory' defined in class path resource [hibernateJPAConfig.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076) 
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851) 
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) 
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84) 
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:42) 
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:173) 
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:197) 
... 17 more 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory 
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) 
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:884) 
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) 
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:340) 
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:319) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) 
... 30 more 
Caused by: org.hibernate.MappingException: broken column mapping for: bookingCorporateDetailsEntity.roomNightEntity of: com.casa.fabbookingbase.entity.RoomNightEntity 
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:165) 
at org.hibernate.persister.entity.AbstractPropertyMapping.initIdentifierPropertyPaths(AbstractPropertyMapping.java:253) 
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:219) 
at org.hibernate.persister.entity.AbstractEntityPersister.initOrdinaryPropertyPaths(AbstractEntityPersister.java:2218) 
at org.hibernate.persister.entity.AbstractEntityPersister.initPropertyPaths(AbstractEntityPersister.java:2265) 
at org.hibernate.persister.entity.AbstractEntityPersister.postConstruct(AbstractEntityPersister.java:3814) 
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:437) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:422) 
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96) 
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77) 
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:344) 
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465) 
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881) 
... 35 more 

PS:我已经看到多个例子在这里,但没能解决甚至在尝试这些解决方案之后的问题

+0

在哪里@Id列?那两个也是表的主键? –

+0

我删除了这个以缩短问题。我的AbstractBookingEntity扩展了具有这个@Id列的AbstractJpaEntity。我只需添加该代码即可。 –

+0

如果我只在一列上加入'room_night_booking_id',但没有多列加入,则完整安装程序正在工作。 –

回答

0

我已经完成了一些测试,并且它只能处理两个连接列,方法是从RoomNightEntity实体中删除mappedBy

你有那种双向映射最终没有父子关系: BookingCorporateDetailsEntity

@OneToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
@JoinColumns({ 
      @JoinColumn(name = "booking_id", referencedColumnName = "booking_id", insertable = false, updatable = false), 
      @JoinColumn(name = "room_night_booking_id", referencedColumnName = "room_night_booking_id", insertable = false, updatable = false) 
    }) 
private RoomNightEntity roomNightEntity; 

RoomNightEntity

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
@JoinColumns({ 
      @JoinColumn(name = "booking_id", referencedColumnName = "booking_id", insertable = false, updatable = false), 
      @JoinColumn(name = "room_night_booking_id", referencedColumnName = "room_night_booking_id", insertable = false, updatable = false) 
    }) 
private BookingCorporateDetailsEntity bookingCorporateDetailsEntity; 
+0

我不希望它是一个双向映射。所以简而言之,在两个表中都存在ID字段的情况下是不可能的。对? –

+0

如果您希望它是单向的,那么只需从Room night实体中删除@onetoone映射,并将其保留在预订实体上即可。您使用mappedBy的原始代码实际上是一种双向映射。 –

+0

我尝试了双向连接,但是我在保存RoomNightEntity的同时得到了外键约束 - org.hibernate.engine.jdbc.spi.SqlExceptionHelper:124 - 无法执行语句[n/a] com.mysql。 jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:无法添加或更新子行:外键约束失败('booking_microservice'。'booking_corporate_details',CONSTRAINT'FKmjasnoswcalcuwyqe2s6m43i7' FOREIGN KEY('booking_id','room_night_booking_id')参考'room_night'('booking_id','room_ni)' –