2009-04-28 2 views
2

나는 Hibernate/JPA에서 작동 시키려고하는 간단한 클래스 계층 구조를 가지고있다.2 개의 테이블 중 최대 절전 모드 엔티티 분할하기

기본적으로 내가 원하는 것은 MovementData가 데이터베이스의 주요 차량 테이블의 정수 ID에 FK를 사용하여 자체 테이블에 있어야한다는 것입니다.

내가 잘못 했나요? 비슷한 다른 것을 어떻게 달성 할 수 있습니까? 나는 JPA 스펙을 따르고 있다고 확신한다. (동작에서 EJB3이 작동합니다 말한다 : 여기에

EJB3 In Action: @SecondaryTable 내가 점점 오전 예외의 일부입니다 :

여기
SEVERE: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session) 
org.hibernate.AssertionFailure: Table MOVEMENT_DATA not found 
    at org.hibernate.persister.entity.JoinedSubclassEntityPersister.getTableId(JoinedSubclassEntityPersister.java:480) 
    at org.hibernate.persister.entity.JoinedSubclassEntityPersister.<init>(JoinedSubclassEntityPersister.java:259) 
    at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:87) 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:261) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327) 

가 차량에 관련된 최대 절전 모드에서 로깅 정보의 일부입니다 ... 그것은을 그것을 잘 모든 것을 인식처럼 .. 그 다음은 어떤 이유로 예외를 throw 보인다.

INFO: Binding entity from annotated class: com.dataobject.Vehicle 
FINE: Import with entity name Vehicle 
INFO: Bind entity com.dataobject.Vehicle on table VEHICLE 
INFO: Adding secondary table to entity com.dataobject.Vehicle -> MOVEMENT_DATA 
FINE: Processing com.dataobject.Vehicle property annotation 
FINE: Processing annotations of com.dataobject.Vehicle.id 
FINE: Binding column id. Unique false. Nullable false. 
FINE: id is an id 
FINE: building SimpleValue for id 
FINE: Building property id 
FINEST: Cascading id with null 
FINE: Bind @Id on id 
FINE: Processing annotations of com.dataobject.Vehicle.color 
FINE: Binding column COLOR. Unique false. Nullable true. 
FINE: binding property color with lazy=false 
FINE: building SimpleValue for color 
FINE: Building property color 
FINEST: Cascading color with null 
FINE: Processing annotations of com.dataobject.Vehicle.movementData 
FINE: Binding column movementData. Unique false. Nullable true. 
FINE: Binding component with path: com.dataobject.Vehicle.movementData 
FINE: Processing com.dataobject.MovementData property annotation 
FINE: Processing annotations of com.dataobject.MovementData.latitude 
FINE: Column(s) overridden for property latitude 
FINE: Binding column LATITUDE. Unique false. Nullable true. 
FINE: binding property latitude with lazy=false 
FINE: building SimpleValue for latitude 
FINE: Building property latitude 
FINEST: Cascading latitude with null 
FINE: Processing annotations of com.dataobject.MovementData.longitude 
FINE: Column(s) overridden for property longitude 
FINE: Binding column LONGITUDE. Unique false. Nullable true. 
FINE: binding property longitude with lazy=false 
FINE: building SimpleValue for longitude 
FINE: Building property longitude 
FINEST: Cascading longitude with null 
FINE: Processing annotations of com.dataobject.MovementData.speed 
FINE: Column(s) overridden for property speed 
FINE: Binding column SPEED. Unique false. Nullable true. 
FINE: binding property speed with lazy=false 
FINE: building SimpleValue for speed 
FINE: Building property speed 
FINEST: Cascading speed with null 
FINE: Processing annotations of com.dataobject.MovementData.timeOfPosition 
FINE: Column(s) overridden for property timeOfPosition 
FINE: Binding column TIME_OF_POSITION. Unique false. Nullable true. 
FINE: binding property timeOfPosition with lazy=false 
FINE: building SimpleValue for timeOfPosition 
FINE: Building property timeOfPosition 
FINEST: Cascading timeOfPosition with null 
FINE: Building property movementData 
FINEST: Cascading movementData with null 
FINE: Processing annotations of com.dataobject.Vehicle.numWheels 
FINE: Binding column NUM_WHEELS. Unique false. Nullable true. 
FINE: binding property numWheels with lazy=false 
FINE: building SimpleValue for numWheels 
FINE: Building property numWheels 
FINEST: Cascading numWheels with null 
INFO: Binding entity from annotated class: com.dataobject.Car 
FINE: Binding column id. Unique false. Nullable false. 
FINE: Subclass joined column(s) created 
FINE: Import with entity name Car 
INFO: Bind entity com.dataobject.Car on table CAR 
FINE: Processing com.dataobject.Car property annotation 
FINE: Processing annotations of com.dataobject.Car.make 
FINE: Binding column MAKE. Unique false. Nullable true. 
FINE: binding property make with lazy=false 
FINE: building SimpleValue for make 
FINE: Building property make 

차량은 부모 클래스

0123입니다
/** 
* Entity implementation class for Entity: Vehicle 
* 
*/ 
@Entity 
@Table(name="VEHICLE") 
@Inheritance(strategy=InheritanceType.JOINED) 
@SecondaryTable(name="MOVEMENT_DATA", 
      pkJoinColumns = { 
       @PrimaryKeyJoinColumn(name = "ID") 
      } 
) 
public class Vehicle implements Serializable { 


    private int numWheels; 
    private String color; 
    private int id; 
    private MovementData movementData; 
    private static final long serialVersionUID = 1L; 


    public Vehicle() { 
     super(); 
    } 

    @Embedded 
    @AttributeOverrides({ 
    @AttributeOverride(
     name = "speed", 
     column = @Column(name = "SPEED", 
         table = "MOVEMENT_DATA") 
    ), 
    @AttributeOverride(
     name = "timeOfPosition", 
     column = @Column(name = "TIME_OF_POSITION", 
         table = "MOVEMENT_DATA") 
    ), 
    @AttributeOverride(
      name = "longitude", 
      column = @Column(name = "LONGITUDE", 
          table = "MOVEMENT_DATA") 
     ), 
    @AttributeOverride(
      name = "latitude", 
      column = @Column(name = "LATITUDE", 
          table = "MOVEMENT_DATA") 
     ) 
}) 
    public MovementData getMovementData() { 
     return movementData; 
    } 
    public void setMovementData(MovementData movementData) { 
     this.movementData = movementData; 
    } 

    @Column(name="NUM_WHEELS") 
    public int getNumWheels() { 
     return this.numWheels; 
    } 

    public void setNumWheels(int numWheels) { 
     this.numWheels = numWheels; 
    } 
    @Column(name="COLOR") 
    public String getColor() { 
     return this.color; 
    } 

    public void setColor(String color) { 
     this.color = color; 
    } 
    @Id  
    public int getId() { 
     return this.id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

} 

자동차 차량

/** 
* Entity implementation class for Entity: Car 
*/ 
@Entity 
@Table(name="CAR") 
public class Car extends Vehicle implements Serializable { 


    private String make; 
    private static final long serialVersionUID = 1L; 

    public Car() { 
     super(); 
    } 
    /** 
    * @return 
    */ 
    @Column(name="MAKE") 
    public String getMake() { 
     return this.make; 
    } 

    /** 
    * @param make 
    */ 
    public void setMake(String make) { 
     this.make = make; 
    } 

} 

MovementData가 차량에 내장되어 확장

@Embeddable 
public class MovementData implements Serializable { 


    private double speed; 
    private Date timeOfPosition; 
    private double latitude; 
    private double longitude; 
    private static final long serialVersionUID = 1L; 

    public MovementData() { 
     super(); 
    } 



    /** 
    * @return 
    */ 
    @Column(name="SPEED") 
    public double getSpeed() { 
     return this.speed; 
    } 

    /** 
    * @param speed 
    */ 
    public void setSpeed(double speed) { 
     this.speed = speed; 
    } 
    /** 
    * @return 
    */ 
    @Column(name="TIME_OF_POSITION") 
    public Date getTimeOfPosition() { 
     return this.timeOfPosition; 
    } 

    /** 
    * @param timeOfPosition 
    */ 
    public void setTimeOfPosition(Date timeOfPosition) { 
     this.timeOfPosition = timeOfPosition; 
    } 

    /** 
    * @return 
    */ 
    @Column(name="LONGITUDE") 
    public double getLongitude() { 
     return this.longitude; 
    } 

    /** 
    * @param longitude 
    */ 
    public void setLongitude(double longitude) { 
     this.longitude = longitude; 
    } 
    /** 
    * @return 
    */ 
    @Column(name="LATITUDE") 
    public double getLatitude() { 
     return this.latitude; 
    } 

    /** 
    * @param latitude 
    */ 
    public void setLatitude(double latitude) { 
     this.latitude = latitude; 
    } 

} 

지속성 단위 :

<properties> 
     <!-- The database dialect to use --> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> 
     <!-- drop and create tables at deployment --> 
     <property name="hibernate.hbm2ddl.auto" value="create-drop" /> 
     <!-- Hibernate Query Language (HQL) parser. --> 
     <!-- property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" /--> 
     <!-- property name="hibernate.cache.provider_class" value="org.hibernate.cache.JbossCacheProvider" /--> 
     <property name ="hibernate.show_sql" value="false" /> 
     <property name ="hibernate.format_sql" value="false" /> 
     <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" /> 
    </properties> 

답변

1

는 그 것이 편리이 속성을 활성화하기 :

CFG 내 AnnotationConfiguration입니다
cfg.setProperty(Environment.HBM2DDL_AUTO, "update"); 

.

이 속성을 활성화하면 문제가 해결 될 가능성이 큽니다. 임베드 클래스의

+0

위의 my persistence.xml을 참조하십시오. 난 그냥 대신 업데이 트와 함께 그것을 시도하고, 그것은 여전히 ​​동일한 오류와 함께 작동하지 않습니다. – systemoutprintln

+1

이 문제가있는 다른 사용자를위한 참고 사항 : 자동 선택되었습니다 ...이 작동하지 않습니다. – systemoutprintln

0

게시 한 예외 때문에 데이터베이스에 테이블이 아직 생성되지 않은 것으로 나타납니다 ('테이블 MOVEMENT_DATA를 찾을 수 없음'). Hibernate/JPA에게 스키마 변경을 지시하지 않았다면, 코드를 실행하기 전에 수동으로 테이블을 추가해야한다. (변경을 수행하기 위해 최대 절전 모드를 지시하는 CREATE-UPDATE이다.) 개발하는 동안

+0

이미 내 persistence.xml에 있습니다. – systemoutprintln

0

정의 해야하지 참조 데이터베이스 테이블 :

@Entity 
@Table(name="VEHICLE") 
@Inheritance(strategy=InheritanceType.JOINED) 
@SecondaryTable(name="MOVEMENT_DATA", 
       pkJoinColumns = { 
        @PrimaryKeyJoinColumn(name = "ID") 
       } 
) 
public class Vehicle implements Serializable { 


    private int numWheels; 
    private String color; 
    private int id; 
    private MovementData movementData; 
    private static final long serialVersionUID = 1L; 


    public Vehicle() { 
     super(); 
    } 

    @Embedded 
    @AttributeOverrides({ 
     @AttributeOverride(
      name = "speed", 
      column = @Column(name = "SPEED", 
          table = "MOVEMENT_DATA") 
     ), 
     @AttributeOverride(
      name = "timeOfPosition", 
      column = @Column(name = "TIME_OF_POSITION", 
          table = "MOVEMENT_DATA") 
     ), 

     ... // override the rest of the attributes 

    }) 
    public MovementData getMovementData() { 
     return movementData; 
    } 

    ... 

    @Id  
    public int getId() { 
     return this.id; 
    } 

    ... 
} 

내가이 뜻을 희망 :

다음
@Embeddable 
public class MovementData implements Serializable { 


    private double speed; 
    private Date timeOfPosition; 
    private double latitude; 
    private double longitude; 
    private static final long serialVersionUID = 1L; 

    public MovementData() { 
     super(); 
    } 

    @Column(name="SPEED") 
    public double getSpeed() { 
     return this.speed; 
    } 

    ... 

    @Column(name="TIME_OF_POSITION") 
    public Date getTimeOfPosition() { 
     return this.timeOfPosition; 
    } 

    ... 

    @Column(name="LONGITUDE") 
    public double getLongitude() { 
     return this.longitude; 
    } 

    ... 

    @Column(name="LATITUDE") 
    public double getLatitude() { 
     return this.latitude; 
    } 

    ... 
} 

차량 엔티티는 열 가입을 포함한 임베디드 구조 에 대한 보조 테이블을 정의해야합니다 당신을 위해 일합니다.

+0

도움을 주셔서 감사합니다 ... 여전히 같은 오류가 발생합니다. 나는 나의 지혜 끝에있다! – systemoutprintln

+1

나는 이런 문제가 생길 때 가능한 한 투명하게 만들기 위해 경기장을 단순화하려고 노력한다. 이 경우에는 Vehicle 엔티티의 상속 설정을 제거합니다. 그 방법으로 한 번에 한 가지 문제를 처리합니다 (잘하면). 보조 테이블에서 임베드 가능 객체의 문제를 해결 한 후 상속을 롤백하고 어떻게 상호 연계되는지 살펴 봅니다. – topchef

1

문제를 찾기 위해이 문제를 해결하려고합니다. 임베딩 가능한 클래스 대신 엔티티에 이동 데이터를 만들어보십시오. 자체적으로 세울 수 있는지 확인한 다음 다시 삽입 가능으로 변경하십시오.

실제로 관계가 아니더라도 MovementData를 루트 부모로 만들고 Vehicle을 MovementData에서 상속받을 수 있습니다. 그렇게하면 상속 + 보조 표 대신

@Inheritance(strategy=InheritanceType.JOINED) 

대신 사용할 수 있습니다. 그것은 관계를 단순화하지만 여전히 모든 테이블을 포함합니다.

+0

아 .. 당신 말이 맞아요. @SecondaryTable과 결합 된 상속 전략을 섞는 것이 문제 일 수 있습니다. 왜냐하면 DB 관점에서 보았을 때 똑같은 것처럼 보였기 때문입니다. 위와 같이 Java Entities를 보이기를 원하기 때문에 실제로 이상적인 솔루션은 아닙니다. – systemoutprintln

+0

그래서 보조 테이블이 아니라 Vehicle과 MovementData 간의 OneToOne 관계만으로 만들 수 있습니다. 맞은 계곡으로 그것은 똑같이 행동 할 것입니다. – ccclark

-1

테이블이 실제로 존재하는지 확인하려면 적절한 db 클라이언트 (Query Browser, MS SQL Managment Studio 등)를 사용하여 데이터베이스에 연결하십시오.

코드에 중단 점을 삽입하면이 오류가 발생하기 전에 데이터베이스의 모양을 정확히 볼 수 있습니다.

는 SQL을 출력하도록 당신이 시도하고 있는지 볼 수 있도록 설정을 "만드는"아래로, 또한 변경하려면 hibernate.hbm2ddl.auto 값을 설정하십시오 :

<props> 
    <!-- some possible values: create, create-drop, update --> 
    <prop key="hibernate.hbm2ddl.auto">update</prop> 
    <prop key="hibernate.show_sql">true</prop> 
    .... 
<props> 

은 알려주세요 DB에서 볼 수있는 것.

+0

내가 만들 때 실제 DB에 아무것도 생성되지 않습니다. 그 시점 이전에 예외가 throw됩니다. 위의 게시물에 로깅 정보를 추가했습니다. – systemoutprintln

+0

다음과 같이 Vehicle의 Id 필드에 Id의 열 이름을 추가하지 마십시오. @Id @Column (name = "ID") public int getId() { return this.id; } – Cuga

1

나는이 방법이 너무 늦은 것 같지만, 뭔가 다른 것을 찾을 때 질문에 비틀 거렸다.

문제는 Embeddable 클래스가 테이블에 매핑되지 않는다는 것입니다. Embeddable 개체는 데이터베이스에 ID가 없습니다.

이 때문에 MovementData 테이블이 생성되지 않습니다.

임베디드의 의미를 혼동스럽게 생각합니다. 이전 주석가가 언급했듯이 Vehicle 및 MovementData는 OneToOne 관계에 있어야하며 포함 된 주석은 제거해야합니다. 차량이 제거 된 경우 MovementData도 제거되도록하려면 계단식 제거 규칙이 필요할 수 있습니다.