文章目录
映射类型
hibernate中的type与JDBC和SQL的数据类型均不相同。Hibernate的类型分为2种:值类型,实体类型。
值类型由实体负责其生命周期,也就是说实体的状态是由值类型维护的,即JavaBean与属性的关系。
值类型
有3类:
- 基本类型
- Embeddable类型
- 集合类型
实体类型
命名策略
- @Column or @Table实现或者通过ImplicitNamingStrategy 实现
- PhysicalNamingStrategy
ImplicitNamingStrategy
当实体没有显式地命名它映射到的数据库表时,我们需要隐式地确定该表名。或者当特定属性没有显式地命名它映射到的数据库列时,我们需要隐式地确定该列名。
pre-defined “short names” for the out-of-the-box implementations
- default for org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl - an alias for jpa
jpa
for org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl - the JPA 2.0 compliant naming strategy
legacy-hbm
for org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl - compliant with the original Hibernate NamingStrategy
legacy-jpa
for org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl - compliant with the legacy NamingStrategy developed for JPA 1.0, which was unfortunately unclear in many respects regarding implicit naming rules
component-path
for org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl - mostly follows ImplicitNamingStrategyJpaCompliantImpl rules, except that it uses the full composite paths, as opposed to just the ending property part
-
reference to a Class that implements the org.hibernate.boot.model.naming.ImplicitNamingStrategy contract
-
FQN of a class that implements the org.hibernate.boot.model.naming.ImplicitNamingStrategy contract
PhysicalNamingStrategy
自定义物理映射关系
@Entity(name = "Contact")
public static class Contact {
@Id
private Integer id;
private Name name;
private String notes;
private URL website;
private boolean starred;
//Getters and setters are omitted for brevity
}
@Embeddable
public class Name {
private String first;
private String middle;
private String last;
// getters and setters omitted
}
@Basic
optional 字段能否为空
fetch 是否懒加载
@Entity(name = "Product")
public class Product {
@Id
@Basic
private Integer id;
@Basic
private String sku;
@Basic
private String name;
@Basic
private String description;
}
@Column
@Entity(name = "Product")
public class Product {
@Id
private Integer id;
private String sku;
private String name;
@Column( name = "NOTES" )
private String description;
}
BasicTypeRegistry
告诉hibernate类型的映射关系。
@Entity(name = "Product")
public class Product {
@Id
private Integer id;
private String sku;
@org.hibernate.annotations.Type( type = "nstring" )
private String name;
@org.hibernate.annotations.Type( type = "materialized_nclob" )
private String description;
}
自定义类型的使用参考文档
映射枚举值
@Enumerated or @MapKeyEnumerated
public enum PhoneType {
LAND_LINE,
MOBILE;
}
@Entity(name = "Phone")
public static class Phone {
@Id
private Long id;
@Column(name = "phone_number")
private String number;
@Enumerated(EnumType.ORDINAL)
@Column(name = "phone_type")
private PhoneType type;
//Getters and setters are omitted for brevity
}
对于ordinal类型:
NULL
For null values
0
For the LAND_LINE enum
1
For the MOBILE enum
相当于执行sql:
INSERT INTO Phone (phone_number, phone_type, id)
VALUES ('123-456-78990', 2, 1)
@Entity(name = "Phone")
public static class Phone {
@Id
private Long id;
@Column(name = "phone_number")
private String number;
@Enumerated(EnumType.STRING)
@Column(name = "phone_type")
private PhoneType type;
//Getters and setters are omitted for brevity
}
INSERT INTO Phone (phone_number, phone_type, id)
VALUES ('123-456-78990', 'MOBILE', 1)
但是对于一些场景,我看可能想做更进一步的自定义转换:
如,M,F表示男女 YN表示是否
public enum Gender {
MALE( 'M' ),
FEMALE( 'F' );
private final char code;
Gender(char code) {
this.code = code;
}
public static Gender fromCode(char code) {
if ( code == 'M' || code == 'm' ) {
return MALE;
}
if ( code == 'F' || code == 'f' ) {
return FEMALE;
}
throw new UnsupportedOperationException(
"The code " + code + " is not supported!"
);
}
public char getCode() {
return code;
}
}
@Entity(name = "Person")
public static class Person {
@Id
private Long id;
private String name;
@Convert( converter = GenderConverter.class )
public Gender gender;
//Getters and setters are omitted for brevity
}
@Converter
public static class GenderConverter
implements AttributeConverter<Gender, Character> {
public Character convertToDatabaseColumn( Gender value ) {
if ( value == null ) {
return null;
}
return value.getCode();
}
public Gender convertToEntityAttribute( Character value ) {
if ( value == null ) {
return null;
}
return Gender.fromCode( value );
}
}
映射LOBS
JDBC的LOB包括:
java.sql.Blob
java.sql.Clob
java.sql.NClob
java类型经常为String, char[], byte[], etc,此类大对象需要权衡性能。
@Entity(name = "Product")
public static class Product {
@Id
private Integer id;
private String name;
@Lob
private byte[] image;
//Getters and setters are omitted for brevity
}
时间类型
@Column(name = "`timestamp`")
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp;
AttributeConverters
@Converter
public class PeriodStringConverter
implements AttributeConverter<Period, String> {
@Override
public String convertToDatabaseColumn(Period attribute) {
return attribute.toString();
}
@Override
public Period convertToEntityAttribute(String dbData) {
return Period.parse( dbData );
}
}
@Entity(name = "Event")
public static class Event {
@Id
@GeneratedValue
private Long id;
@Convert(converter = PeriodStringConverter.class)
@Column(columnDefinition = "")
private Period span;
//Getters and setters are omitted for brevity
}
INSERT INTO Event ( span, id )
VALUES ( 'P1Y2M3D', 1 )
SQL限定符
@Entity(name = "Product")
public static class Product {
@Id
private Long id;
@Column(name = "`name`")
private String name;
@Column(name = "`number`")
private String number;
//Getters and setters are omitted for brevity
}
JPA方式:
@Entity(name = "Product")
public static class Product {
@Id
private Long id;
@Column(name = "\"name\"")
private String name;
@Column(name = "\"number\"")
private String number;
//Getters and setters are omitted for brevity
}
hibernate也可以全职设置
<property
name="hibernate.globally_quoted_identifiers"
value="true"
/>
@CreationTimestamp annotation
@UpdateTimestamp annotation
类转换(加密解密) @ColumnTransformer
@Entity(name = "Employee")
public static class Employee {
@Id
private Long id;
@NaturalId
private String username;
@Column(name = "pswd")
@ColumnTransformer(
read = "decrypt( 'AES', '00', pswd )",
write = "encrypt('AES', '00', ?)"
)
private String password;
private int accessLevel;
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
@ManyToMany(mappedBy = "employees")
private List<Project> projects = new ArrayList<>();
//Getters and setters omitted for brevity
}