Разделение спящего объекта на две таблицы - PullRequest
2 голосов
/ 28 апреля 2009

У меня есть простая иерархия классов, которую я пытаюсь заставить работать с Hibernate / JPA.

В основном я хочу, чтобы MovementData находился в своей собственной таблице с FK для целочисленного идентификатора главной таблицы транспортных средств в базе данных.

Я что-то не так делаю? Как еще я могу сделать что-то подобное? Я почти уверен, что следую спецификации JPA. (EJB3 в действии говорит, что это должно работать: EJB3 в действии: @ 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, которая относится к Транспортному средству ... Похоже, что он все прекрасно распознает ... Затем он по какой-то причине вызывает исключение.

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 ]

1 голос
/ 09 ноября 2012

Наверное, слишком поздно для этого, но я наткнулся на вопрос, когда искал что-то еще.

Проблема в том, что класс Embeddable не сопоставляется с таблицей - объект Embeddable не имеет идентификатора в базе данных.

Вот почему не создается таблица MovementData.

Я думаю, что вы перепутали значение Embedded. Как упоминалось предыдущим комментатором, Vehicle и MovementData должны находиться в отношении OneToOne, а встроенные аннотации должны быть удалены. Возможно, вам понадобится правило каскадного удаления, чтобы убедиться, что если транспортное средство удалено, то и MovementData.

1 голос
/ 04 мая 2009

Я бы попытался разобраться в этом, чтобы найти проблему. Попробуйте преобразовать данные о перемещении в сущность, а не встраиваемый класс. Убедитесь, что он может стоять самостоятельно, а затем измените его обратно на встраиваемый.

Хотя это не совсем то отношение, которое вам нужно, вы можете попытаться сделать MovementData корневым родителем и получить наследование Vehicle от MovementData. Таким образом, вы будете работать только с

@Inheritance(strategy=InheritanceType.JOINED)

вместо наследования плюс вторичная таблица. Это упростило бы отношения, но все равно включало бы все таблицы.

1 голос
/ 29 апреля 2009

Во время разработки часто бывает удобно включить это свойство:

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

где cfg - это моя конфигурация аннотации.

Ваша проблема, скорее всего, будет решена включением этого свойства.

0 голосов
/ 06 мая 2009

Подключитесь к вашей базе данных, используя соответствующий клиент БД (Query Browser, MS SQL Managment Studio и т. Д.), Чтобы проверить, существуют ли таблицы на самом деле.

Возможно, вы также захотите вставить точку останова в свой код, чтобы вы могли точно видеть, как выглядит база данных в момент, когда она выдает эту ошибку.

Попробуйте установить для значения hibernate.hbm2ddl.auto значение «создать», как показано ниже, а также измените параметр так, чтобы он выводил SQL-код, чтобы вы могли видеть, что он пытается:

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

Дайте мне знать, что вы видите в своей БД.

0 голосов
/ 02 мая 2009

Определение встраиваемого класса не должно ссылочная таблица базы данных:

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

    ...
}

Надеюсь, это сработает для вас.

0 голосов
/ 28 апреля 2009

Из исключения, которое вы опубликовали, создается впечатление, что таблица еще не была создана в вашей базе данных ("Таблица MOVEMENT_DATA не найдена"). Если вы не указали Hibernate / JPA изменить свою схему, вы должны вручную добавить таблицу перед запуском вашего кода (я полагаю, что CREATE-UPDATE указывает Hibernate на выполнение изменения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...