Сопоставление двух объектов с использованием столбца общего внешнего ключа в спящем режиме - PullRequest
0 голосов
/ 21 сентября 2010

У меня есть четыре объекта для сопоставления: «Ассоциация», «Учетная запись», «Транзакция» и «TransactionEvent». Идентификатор ассоциации - это простой целочисленный идентификатор. Учетная запись и транзакция имеют встроенные идентификаторы, состоящие из сопоставления с ассоциацией и номером.

TransactionEvent должен иметь встроенный идентификатор, состоящий из одной учетной записи и одной ассоциации. Теперь каждый из них сопоставлен с Ассоциацией, и я хочу, чтобы это была одна и та же Ассоциация для одного TransactionEvent.

JPA Annotations используется для отображения Hibernate, но я не могу сделать эту работу. Я пытался принудительно использовать одно и то же имя столбца для ключа ассоциации, но Hibernate жалуется на повторяющиеся столбцы.

Возможно ли это решить, или я не думаю прямо?

Вот аннотированные классы, но я обрезал методы получения / установки и столбцы без идентификаторов, аннотации из пространства имен javax.persistence:


@Entity
public class Association implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
}

@Embeddable
public class AccountPK implements Serializable {
    @ManyToOne(optional=false)
    private Association association;

    @Column(nullable=false)
    private int number;
}

@Embeddable
public class TransactionPK implements Serializable {
    @ManyToOne
    private Association association;

    @GeneratedValue(strategy=GenerationType.AUTO)
    private long number;
}

@Embeddable
public class AccountEventPK implements Serializable {
    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="account_number", referencedColumnName="number")
    })
    private Account account;

    @ManyToOne(optional=false)
    @JoinColumns({
        @JoinColumn(name="association_id", referencedColumnName="association_id"),
        @JoinColumn(name="transaction_number", referencedColumnName="number")
    })
    private Transaction transaction;
}

Фактическая сущность Account, Transaction и AccountEvent находятся в форме


@Entity
public class Account implements Serializable {
        @EmbeddedId
        private AccountPK id;
}

1 Ответ

2 голосов
/ 22 сентября 2010

У меня нет большого опыта размещения ассоциаций непосредственно во встроенном компоненте id, так как это не поддерживается JPA, но относится к Hibernate.

В качестве альтернативы я бы предложил использовать подход, описанный в разделе Составные первичные ключи в викибуке JPA:

(...) JPA1.0 требует, чтобы все @Id отображений были Basic отображениями, поэтому, если ваш идентификатор поступает из столбца внешнего ключа через отображение OneToOne или ManyToOne, вы также должны определить базовое отображение @Id для столбца внешнего ключа.Это частично объясняется тем, что идентификатор должен быть простым объектом для целей идентификации и кэширования, а также для использования в IdClass или EntityManager find() API.

Поскольку выТеперь у вас есть два сопоставления для одного и того же столбца внешнего ключа, вы должны определить, какой из них будет записан в базу данных (это должен быть базовый), поэтому внешний ключ OneToOne или ManyToOne должен быть определен только для чтения.Это можно сделать, установив для атрибутов JoinColumn insertable и updatable значение false или используя @PrimaryKeyJoinColumn вместо @JoinColumn.

Побочный эффект наличия двух сопоставленийдля того же столбца в том, что теперь вы должны синхронизировать два.Обычно это делается с помощью того, что метод set для атрибута OneToOne также устанавливает в качестве значения атрибута Basic идентификатор целевого объекта.Это может стать очень сложным, если первичный ключ целевого объекта - GeneratedValue, в этом случае вы должны убедиться, что идентификатор целевого объекта был назначен, прежде чем связывать два объекта.

(...)

Пример ManyToOne id-аннотация

...
@Entity
@IdClass(PhonePK.class)
public class Phone {
    @Id
    @Column(name="OWNER_ID")
    private long ownerId;

    @Id
    private String type;

    @ManyToOne
    @PrimaryKeyJoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...

    public void setOwner(Employee owner) {
        this.owner = owner;
        this.ownerId = owner.getId();
    }
    ...
}

Это выглядит как то, что вы ищете (и, возможно, не так сложно).Я бы попробовал реализовать это решение (постепенно).

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