Hibernate / JPA - индекс внешнего ключа в самом объекте - PullRequest
1 голос
/ 13 июля 2009

В настоящее время я работаю над 100+ объектами Java, созданными кем-то, у кого нет опыта JPA / Hibernate в объектах JPA. Их объекты ссылаются на другие объекты на основе внешнего ключа в самом классе. Все первичные ключи генерируются вне базы данных.

Например (просто для иллюстрации)

Car

@Entity
@Table(name="CAR")
public class Car {

    private Integer id;
    private String name;

    @Id
    @Column(name="CAR_ID")
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name="CAR_NAME")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

Двигатель

@Entity
@Table(name="ENGINE")
public class Engine {

    private Integer id;
    private String name;
    private Integer carId;

    @Id
    @Column(name="ENGINE_ID")
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name="ENGINE_NAME")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name="CAR_ID")
    public Integer getCarId() {
        return carId;
    }
    public void setCarId(Integer carId) {
        this.carId = carId;
    }

}

Вот как выглядит схема:

CREATE TABLE CAR(CAR_ID INTEGER NOT NULL PRIMARY KEY,CAR_NAME VARCHAR(255))
CREATE TABLE ENGINE(ENGINE_ID INTEGER NOT NULL PRIMARY KEY,CAR_ID INTEGER,ENGINE_NAME VARCHAR(255))
ALTER TABLE ENGINE ADD FOREIGN KEY (CAR_ID) REFERENCES CAR(CAR_ID) ON DELETE CASCADE ON UPDATE CASCADE

Код тестирования

    Car c = new Car();
    c.setId(100);
    c.setName("Dodge Intrepid");
    em.persist(c);

    Engine e = new Engine();
    e.setId(999);
    e.setName("V6");
    e.setCarId(c.getId());
    em.persist(e);

    Object entity = em.find(c.getClass(),c.getId());
    em.remove(entity);

Итак, идентификатор автомобиля содержит ссылку на двигатель в базе данных. Потеря Lazy Loading не имеет большого значения, потому что мы используем TRANSACTIONAL Entity Manager. Я проверил это, и, кажется, работает нормально.

Есть ли какие-то очевидные проблемы с этим, которые я пропускаю? Я знаю, что он не совсем соответствует спецификации JPA / Hibernate, но я думаю, что он работает.

Ответы [ 2 ]

3 голосов
/ 13 июля 2009

Главное, что вы теряете, - это простая навигация по графу объектов без необходимости явного извлечения связанных объектов по идентификатору все время через слой доступа к данным. Я понимаю, что вы неохотно проходите и конвертируете все идентификаторы объектов в ссылки на объекты, но в долгосрочной перспективе вам, вероятно, будет лучше сделать эти инвестиции. Продолжая свой текущий дизайн, вы в конечном итоге напишите много дополнительного кода доступа к данным для извлечения связанных объектов каждый раз, когда вам нужно перемещаться по ассоциации. Кроме того, это усложнит моделирование объектных отношений, когда объекты не сохраняются в базе данных (например, при построении нового графа объектов или в модульных тестах). Вы также отказываетесь от каскадных (транзитивных) сохранений и обновлений.

Короче говоря, я думаю, что ваша система будет труднее поддерживать в долгосрочной перспективе, и навигация по графам объектов будет довольно неудобной, если вы не решите эту проблему проектирования.

1 голос
/ 14 июля 2009

Отсутствие каких-либо сопоставленных отношений сделает почти невозможным наличие каких-либо объединений в ваших HQL-запросах или критериях. Простой Select будет работать, но вы не могли сделать

from Engine as eng where eng.car.name = 'DODGE'

Если вы, по крайней мере, закодируете основные отношения, это в конечном итоге значительно облегчит ситуацию.

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