2017-02-10 6 views
2

У меня есть две сущности RoomNight и BookingCorporateDetails, в которых BookingCorporateDetails ссылается RoomNight на две колонки (booking_id и room_night_booking_id).Разбитое Mapping Колонка для одного до нескольких Один столбец внешнего ключа

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

Я удалил это, чтобы укоротить вопрос. My AbstractBookingEntity расширяет AbstractJpaEntity, который имеет этот столбец @Id. Позвольте мне просто добавить этот код. –

+0

Полная настройка работает, если я помещаю Join только на один столбец 'room_night_booking_id', но не с несколькими объединениями столбцов. –

ответ

0

Я провел несколько тестов, и единственный способ, которым он работает с двумя столбцами соединения, - удалить mappedBy из объекта RoomNightEntity.

Вы в конечном итоге с рода двунаправленного отображения без отношений родитель-ребенок: 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

. Я не хочу, чтобы это было двунаправленное отображение. Поэтому простыми словами это невозможно при наличии поля идентификатора в обеих таблицах. Правильно? –

+0

Если вы хотите, чтобы он был однонаправленным, просто удалите отображение @onetoone из ночного объекта Room и просто сохраните его на объекте бронирования. Исходный код, в котором вы использовали mappedBy, был фактически двунаправленным отображением. –

+0

Я попробовал объединение Bi-Direction, как вы объяснили, но я получил ограничение внешнего ключа при сохранении 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)' –