Отображение Hibernate: один столбец для нескольких таблиц - PullRequest
8 голосов
/ 01 декабря 2011

У меня есть вопрос «передового опыта» для сценария.

Сценарий: Несколько объектов в БД, например, Document, BlogPost, Wiki, могут совместно использоваться отдельными лицами. Вместо создания таблицы общего доступа для каждой сущности создается отдельная таблица общего доступа. Вопрос в том, как сопоставить таблицу общего доступа с различными объектами?

У меня есть три варианта, пожалуйста, посоветуйте, какой вариант лучше, и если есть лучший вариант.

Option1: Создать таблицу Акции как:

SHARES  
id (unique)
entityId (non DB enforced FK to DOCUMENTS, WIKIS, POSTS etc.)
entityType
sharedBy
sharedWith
sharedDate

Здесь, entityId будет FK для documentId, wikiId, postId и т. Д. И т. Д., А entityType будет идентифицировать, какой тип entityId.

Это имеет проблемы при моделировании Hibernate при создании сопоставления общего ресурса с сущностью, такого как share.getDocument () или share.getWiki () и т. Д.

Вариант 2: Создайте общие таблицы, которые содержат только информацию об общем ресурсе, а затем создайте таблицы разрешения, которые связывают общий ресурс с сущностью.

SHARES
id(PK)
sharedBy
sharedWith
sharedDate
shareType (helper field for searches)

SHARES_DOCUMENTS
share_id (unique ID and FK, one to one with SHARES)
document_id (FK to DOCUMENTS)

SHARES_POST
share_id (unique ID and FK, one to one with SHARES)
post_id (FK to POSTS)

more share tables here.

Таким образом, в спящем режиме Share может иметь одно к одному для каждого из типов общих ресурсов (например, share.getDocument (), share.getPost () и shareType будет определять, какие отношения являются «активными»)

Вариант 3 Аналогичен варианту 1, но вместо идентификатора объекта создаются отдельные столбцы

SHARES
id (unique ID)
documentId (FK to DOCUMENTS, nullable)
postId (FK to POSTS, nullable)
wikiId (FK to WIKIS, nullable)
sharedBy
sharedWith
sharedDate
sharedType

Здесь каждый столбец может быть сопоставлен с соответствующим объектом, но они могут иметь значение NULL. sharedType может определить, какие отношения являются «активными».

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

Спасибо М. Скорее

Ответы [ 2 ]

4 голосов
/ 08 декабря 2011

По предложению TheStijn, после изучения различных способов настройки отношений наследования я выбрал подход «Одна таблица для иерархии классов» и в итоге получил таблицу типа:

SHARES
---------
id PK
shared_by FK to User
shared_with FK to User
shared_Date
document_id nullable FK to Document
post_id nullable FK to Posts
... more ids here to link to more entities
type_discriminator (values, DOCUMENT, POST ... )

В Hibernate /Java сторона, One Share абстрактный класс как ...

@Entity
@Table(name="SHARES")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE_DISCRIMINATOR", discriminatorType=DiscriminatorType.STRING)
public abstract class Share {
    @Id
    @Column( name="ID", nullable=false )
    @GeneratedValue(generator="system-uuid")
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    private String id;

    @ManyToOne
    @JoinColumn( name="SHARED_BY", nullable=false )
    private User sharedBy;

    @ManyToOne
    @JoinColumn( name="SHARED_WITH", nullable=false )
    private User sharedWith;

    @Column(name="SHARED_DATE", columnDefinition="TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP", nullable=false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date sharedDate;        
    ...

}

И два обычных класса ..

@Entity
@DiscriminatorValue("DOCUMENT")
public class SharedDocument extends Share { 
    @ManyToOne
    @JoinColumn( name="DOCUMENT_ID", nullable=true )
    private Document document;
    ....

}

@Entity
@DiscriminatorValue("POST")
public class SharedPost extends Share {
    @ManyToOne
    @JoinColumn( name="POST_ID", nullable=true )
    private Post post;
    ....

}

Что касается использования, используйте конкретные классы только как:

@Test
public void saveNewDocumentShare(){
    SharedDocument sharedDocument = new SharedDocument();
    sharedDocument.setDocument(document1);
    sharedDocument.setSharedBy(teacher1);
    sharedDocument.setSharedWith(teacher2);
    sharedDocument.setSharedDate(new Date());

    sharedDocument.setCreatedBy("1");
    sharedDocument.setCreatedDate(new Date());
    sharedDocument.setModifiedBy("1");
    sharedDocument.setModifiedDate(new Date());


    SharedDocument savedSharedDocument = dao.saveSharedDocument(sharedDocument);

    assertNotNull(savedSharedDocument);
    assertThat(savedSharedDocument.getId(),notNullValue());
}

@Test
public void saveNewPostShare(){
    SharedPost sharedWikiPage = new SharedWikiPage();
    sharedPost.setPost(post1);
    sharedPost.setSharedBy(teacher1);
    sharedPost.setSharedWith(teacher2);
    sharedPost.setSharedDate(new Date());

    sharedPost.setCreatedBy("1");
    sharedPost.setCreatedDate(new Date());
    sharedPost.setModifiedBy("1");
    sharedPost.setModifiedDate(new Date());


    SharedPost savedSharedPost = dao.saveSharedPost(sharedPost);

    assertNotNull(savedSharedPost);
    assertThat(savedSharedPost.getId(),notNullValue());

}
0 голосов
/ 01 декабря 2011

Очевидно, что это отношение «многие ко многим».

Сценарий по умолчанию для отображения этих типов вещей заключается в использовании отдельной таблицы для информации о соединении.Что-то вроде:

table shared_connections {
    number owner_id
    ,number shared_id
}

Все объекты, которые являются общими, должны расширять некоторый базовый класс, например: AbstractSharedObject.(используйте аннотацию @MappedSuperclass и следите за стратегией @Inheritance).

и внутри индивидуального класса:

private Collection<AbstractSharedObject> shares;

отобразите эту коллекцию как ManyToMany отношение.

PS Чтобы это работало, вам нужно будет гарантировать, что идентификаторы всех разделяемых объектов уникальны.

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