在2个表中拆分Hibernate实体

时间:2009-04-28 17:44:36

标签: java hibernate jpa java-ee orm

我有一个简单的类层次结构,我试图使用Hibernate / JPA。

基本上我想要的是MovementData在其自己的表中,其FK为数据库中主车辆表的整数id。

我做错了吗?我怎样才能完成类似的事情呢? 我很确定我遵循JPA规范。 (EJB3 In Action说这应该有效: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)

以下是来自Hibernate的一些与Vehicle有关的日志信息...看起来它正在识别一切正常..然后由于某种原因抛出异常。

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

车辆是父类

/**
 * 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>

6 个答案:

答案 0 :(得分:1)

在开发过程中,启用此属性通常很方便:

cfg.setProperty(Environment.HBM2DDL_AUTO, "update");

其中cfg是我的AnnotationConfiguration。

您的问题最有可能通过启用此属性来解决。

答案 1 :(得分:1)

我会尝试将其分解以找到问题。尝试将移动数据转换为实体而不是嵌入类。确保它可以自行站立,然后将其更改为可嵌入。

虽然它不是你想要的关系,但你可以尝试将MovementData作为根父,并使Vehicle继承MovementData。那样你只会使用

@Inheritance(strategy=InheritanceType.JOINED)

而不是继承加上secondaryTable。它会简化关系,但仍然包括所有表。

答案 2 :(得分:1)

我觉得这样做太迟了,但在寻找别的东西时我偶然发现了这个问题。

问题是Embeddable类没有映射到表 - Embeddable对象在数据库中没有标识。

这就是没有生成MovementData表的原因。

我认为你已经混淆了嵌入式的含义。正如前一位评论者所提到的,Vehicle和MovementData应该处于OneToOne关系中,并且应该删除嵌入式注释。您可能需要Cascade Remove规则以确保在移除车辆时,MovementData也是如此。

答案 3 :(得分:0)

从您发布的例外情况看,似乎尚未在您的数据库中创建表(“未找到表MOVEMENT_DATA”)。如果您没有指示Hibernate / JPA更改模式,则必须在运行代码之前手动添加表(我相信它是CREATE-UPDATE以指示hibernate执行更改)。

答案 4 :(得分:0)

embeddable class 的定义不应该引用数据库表:

@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;
    }

    ...
}

然后,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")
        ),

        ... // override the rest of the attributes

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

    ...

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

    ...
}

我希望这对你有用。

答案 5 :(得分:-1)

使用适当的数据库客户端(查询浏览器,MS SQL Managment Studio等)连接到您的数据库,以验证这些表是否确实存在。

您可能还希望在代码中插入一个断点,以便在它抛出此错误之前,您可以准确地看到数据库的样子。

尝试将hibernate.hbm2ddl.auto值设置为“create”,如下所示,并更改设置以便打印出SQL,以便您可以看到它正在尝试的内容:

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

让我知道您在数据库中看到的内容。