基本映射概念
学习Hibernate时,许多人喜欢跳到父子关联,而无需掌握对象关系映射的基础知识。 在开始对实体关联进行建模之前,了解各个实体的基本映射规则非常重要。
休眠类型
休眠类型是SQL类型和Java原语/对象类型之间的桥梁。
这些是Hibernate默认支持的类型:
休眠类型(org.hibernate.type) | JDBC类型 | Java类型 |
---|---|---|
StringType | VARCHAR | 串 |
物化球 | CLOB | 串 |
文字类型 | LONGVARCHAR | 串 |
角色类型 | 焦炭 | 字符或字符 |
布尔型 | 比特 | 布尔值或布尔值 |
NumericBooleanType | 整数(例如0 =假和1 =真) | 布尔值或布尔值 |
是否类型 | CHAR(例如,“ N”或“ n” = false,“ Y”或“ y” = true) | 布尔值或布尔值 |
TrueFalseType | CHAR(例如,“ F”或“ f” =否,“ T”或“ t” =真) | 布尔值或布尔值 |
字节类型 | 天音 | 字节或字节 |
短型 | SMALLINT | 短或短 |
整数类型 | 整数 | 整型或整型 |
长型 | 比金特 | 长或长 |
浮动类型 | 浮动 | 浮动或浮动 |
双重类型 | 双 | 双倍或双倍 |
BigIntegerType | 数字 | 大整数 |
BigDecimalType | 数字 | 大十进制 |
时间戳类型 | 时间戳 | java.sql.Timestamp或java.util.Date |
时间类型 | 时间 | java.sql.Time |
日期类型 | 日期 | java.sql.Date |
CalendarType | 时间戳 | java.util.Calendar或java.util.GregorianCalendar |
CalendarType | 日期 | java.util.Calendar或java.util.GregorianCalendar |
货币类型 | VARCHAR | java.util.Currency |
语言环境类型 | VARCHAR | java.util.Locale |
时区类型 | VARCHAR | java.util.TimeZone |
网址类型 | VARCHAR | java.net.URL |
类类型 | VARCHAR | java.lang.Class |
BlobType | BLOB | java.sql.Blob |
ClobType | CLOB | java.sql.Clob |
BinaryType | VARBINARY | 字节[]或字节[] |
BinaryType | BLOB | 字节[]或字节[] |
BinaryType | LONGVARBINARY | 字节[]或字节[] |
BinaryType | LONGVARBINARY | 字节[]或字节[] |
CharArrayType | VARCHAR | char []或Character [] |
UUIDBinaryType | 二进制 | java.util.UUID |
UUIDBinaryType | CHAR或VARCHAR | java.util.UUID |
UUIDBinaryType | PostgreSQL UUID | java.util.UUID |
SerializableType | VARBINARY | 可序列化 |
您将始终可以定义自己的自定义类型,我们将在以后的文章中看到。
嵌入式(aka组件)类型
您可以将多个列分组为特定的Java类型,该类型可以在整个域模型中重复使用。 如果映射的Java对象始终依赖于某些外部实体,则可以为此类域模型映射选择Embeddable类型。
一个Embeddable对象可以包含基本类型和关联映射,但不能包含@Id。 可嵌入对象及其拥有的实体将被持久保存/删除。
假设我们有下面的SQL表:
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对象如下所示:
@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; }
}
关联的Entity表将继承Embeddable属性的关联列。
实体
实体与SQL表行的Java等效。 该实体必须包含一个@Id属性,该属性映射关联的表主键。
应用程序逻辑对实体属性进行更改,并向持久性上下文通知实体状态更改(持久,合并,删除)。 因此,持久性上下文会将所有实体更改转换为SQL语句。
假设我们有以下SQL表:
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列。
@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,以查看Embeddable如何与拥有的实体一起持久保存:
@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;
}
});
}
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上获得 。
翻译自: https://www.javacodegeeks.com/2014/06/a-beginners-guide-to-hibernate-types.html