Основные картографические концепции
При изучении Hibernate многим нравится переходить к родительско-дочерним ассоциациям, не осваивая основы сопоставления объектных отношений. Очень важно понять основные правила отображения для отдельных сущностей перед началом моделирования связей сущностей.
Спящие типы
Тип Hibernate — это мост между типом SQL и примитивом Java / типом Object.
Это типы, которые Hibernate поддерживает по умолчанию:
Тип гибернации (org.hibernate.type) | Тип JDBC | Тип Java |
---|---|---|
StringType | VARCHAR | строка |
MaterializedClob | CLOB | строка |
TextType | LONGVARCHAR | строка |
CharacterType | CHAR | символ или персонаж |
BooleanType | НЕМНОГО | логическое или логическое |
NumericBooleanType | INTEGER (например, 0 = ложь и 1 = истина) | логическое или логическое |
YesNoType | CHAR (например, «N» или «n» = false и «Y» или «y» = true) | логическое или логическое |
TrueFalseType | CHAR (например, «F» или «f» = false и «T» или «t» = true) | логическое или логическое |
ByteType | TINYINT | байт или байт |
ShortType | SMALLINT | короткий или короткий |
IntegerType | INTEGER | int или Integer |
LongType | BIGINT | длинный или длинный |
FloatType | FLOAT | плавать или плавать |
DoubleType | DOUBLE | двойной или двойной |
BigIntegerType | NUMERIC | BigInteger |
BigDecimalType | NUMERIC | BigDecimal |
TimestampType | TIMESTAMP | java.sql.Timestamp или java.util.Date |
TimeType | ВРЕМЯ | java.sql.Time |
DateType | ДАТА | java.sql.Date |
CalendarType | TIMESTAMP | java.util.Calendar или java.util.GregorianCalendar |
CalendarType | ДАТА | java.util.Calendar или java.util.GregorianCalendar |
Тип валюты | VARCHAR | java.util.Currency |
LocaleType | VARCHAR | java.util.Locale |
TimeZoneType | VARCHAR | java.util.TimeZone |
UrlType | VARCHAR | java.net.URL |
ClassType | VARCHAR | java.lang.Class |
BlobType | большой двоичный объект | java.sql.Blob |
ClobType | CLOB | java.sql.Clob |
BinaryType | VARBINARY | байт [] или байт [] |
BinaryType | большой двоичный объект | байт [] или байт [] |
BinaryType | LONGVARBINARY | байт [] или байт [] |
BinaryType | LONGVARBINARY | байт [] или байт [] |
CharArrayType | VARCHAR | символ [] или символ [] |
UUIDBinaryType | BINARY | java.util.UUID |
UUIDBinaryType | CHAR или VARCHAR | java.util.UUID |
UUIDBinaryType | PostgreSQL UUID | java.util.UUID |
SerializableType | VARBINARY | Сериализуемый |
Вы всегда можете определить свои собственные пользовательские типы, как мы увидим в следующей статье.
Типы встраиваемых (он же компонент)
Вы можете сгруппировать несколько столбцов для определенного типа Java, который можно повторно использовать в модели вашего домена. Если сопоставленный Java-объект всегда зависит от некоторого внешнего объекта, вы можете выбрать тип Embeddable для такого сопоставления модели домена.
Встраиваемый объект может содержать как базовые типы, так и сопоставления ассоциаций, но он никогда не может содержать @Id. Объект Embeddable сохраняется / удаляется вместе со своим владельцем.
Предполагая, что у нас есть следующая таблица SQL:
1
2
3
4
5
6
7
8
|
CREATE TABLE entity_event ( id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1), entity_class VARCHAR (255), entity_id BIGINT , message VARCHAR (255), PRIMARY KEY (id) ); |
Мы могли бы сгруппировать entity_class и entity_id в объект Embeddable, который мы будем использовать в двух разных сущностях-владельцах.
Объект Embeddable выглядит так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@Embeddable public class EntityIdentifier implements Serializable { @Column (name = "entity_id" , nullable = true ) private Long entityId; @Column (name = "entity_class" , nullable = true ) private Class entityClass; public EntityIdentifier() { } public EntityIdentifier(Class entityClass, Long entityId) { this .entityClass = entityClass; this .entityId = entityId; } public Class getEntityClass() { return entityClass; } public void setEntityClass(Class entityClass) { this .entityClass = entityClass; } public Long getEntityId() { return entityId; } public void setEntityId(Long entityId) { this .entityId = entityId; } } |
Связанная таблица сущностей будет наследовать связанные свойства столбцов Embeddable.
сущность
Entity — это Java-эквивалент строки таблицы SQL. Сущность должна содержать свойство @Id, сопоставляющее связанный первичный ключ таблицы.
Логика приложения вносит изменения в свойства сущностей и уведомляет об изменениях состояния постоянства контекста сущностей (сохраняются, объединяются, удаляются). Поэтому постоянный контекст будет переводить все изменения сущностей в операторы SQL.
Предполагая, что у нас есть следующие таблицы SQL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
CREATE TABLE entity_attribute ( id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1), entity_class VARCHAR (255), entity_id BIGINT , name VARCHAR (255), VALUE VARCHAR (255), PRIMARY KEY (id) ); CREATE TABLE entity_event ( id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1), entity_class VARCHAR (255), entity_id BIGINT , message VARCHAR (255), PRIMARY KEY (id) ); |
Мы можем использовать тип EntityIdentifier Embeddable, поскольку обе таблицы содержат столбцы entity_class и entity_id.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
@Entity @Table (name = "entity_attribute" ) public class EntityAttribute { @Id @GeneratedValue private Long id; private String name; private String value; private EntityIdentifier entityIdentifier; public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getValue() { return value; } public void setValue(String value) { this .value = value; } public EntityIdentifier getEntityIdentifier() { return entityIdentifier; } public void setEntityIdentifier(EntityIdentifier entityIdentifier) { this .entityIdentifier = entityIdentifier; } } @Entity @Table (name = "entity_event" ) public class EntityEvent { @Id @GeneratedValue private Long id; private String message; private EntityIdentifier entityIdentifier; public Long getId() { return id; } public String getMessage() { return message; } public void setMessage(String message) { this .message = message; } public EntityIdentifier getEntityIdentifier() { return entityIdentifier; } public void setEntityIdentifier(EntityIdentifier entityIdentifier) { this .entityIdentifier = entityIdentifier; } } |
Время тестирования
Мы создадим один EntityEvent и один EntityAttribute для данного Продукта, чтобы увидеть, как встраиваемый объект сохраняется вместе с владельцами объектов:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@Test public void testEntityIdentifier() { doInTransaction( new TransactionCallable<Void>() { @Override public Void execute(Session session) { Product product = new Product( "LCD" ); session.persist(product); EntityEvent productEvent = new EntityEvent(); productEvent.setMessage(String.format( "Product %s added" , product.getName())); productEvent.setEntityIdentifier( new EntityIdentifier( product.getClass(), product.getId() )); session.persist(productEvent); EntityAttribute productAttribute = new EntityAttribute(); productAttribute.setName( "AD_CAMPAIGN" ); productAttribute.setValue( "LCD_Sales" ); productAttribute.setEntityIdentifier( new EntityIdentifier( product.getClass(), product.getId() )); session.persist(productAttribute); assertSame( 1 , session.createQuery( "select ea from EntityAttribute ea where ea.entityIdentifier = :entityIdentifier" ) .setParameter( "entityIdentifier" , new EntityIdentifier(product.getClass(), product.getId())) .list().size()); return null ; } }); } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
Query:{[ INSERT INTO product (id, name ) VALUES ( DEFAULT , ?) ][LCD]} Query:{[ INSERT INTO entity_event (id, entity_class, entity_id, message) VALUES ( DEFAULT , ?, ?, ?) ][com.vladmihalcea.hibernate.masterclass.laboratory.entityidentifier.Product,1,Product LCD added]} Query:{[ INSERT INTO entity_attribute (id, entity_class, entity_id, name , VALUE) VALUES ( DEFAULT , ?, ?, ?, ?) ][com.vladmihalcea.hibernate.masterclass.laboratory.entityidentifier.Product,1,AD_CAMPAIGN,LCD_Sales]} Query:{[ SELECT entityattr0_.id AS id1_0_, entityattr0_.entity_class AS entity_c2_0_, entityattr0_.entity_id AS entity_i3_0_, entityattr0_. name AS name4_0_, entityattr0_.VALUE AS value5_0_ FROM entity_attribute entityattr0_ WHERE entityattr0_.entity_class = ? AND entityattr0_.entity_id = ? ][com.vladmihalcea.hibernate.masterclass.laboratory.entityidentifier.Product,1]} |
Вывод
Есть еще много понятий, которые мы должны охватить, прежде чем понять ассоциации сущностей. Прежде чем переходить к более сложным темам, вы всегда должны уделять время пониманию основных понятий. Мой следующий пост будет посвящен идентификаторам сущностей и всем доступным методам генерации.
- Код доступен на GitHub .
Ссылка: | Руководство для начинающих по Hibernate Types от нашего партнера JCG Влада Михалча в блоге Влада Михалча . |