JPA 实体映射
来源:互联网 发布:如果黄家驹还活着知乎 编辑:程序博客网 时间:2024/06/05 06:43
1、 实体映射
@Entity
@Table(name="T_STUDENT",uniqueConstraints=@UniqueConstraint(columnNames="name"))
public class Student implements Serializable
{
private static final long serialVersionUID = 1L;
private int id;
private Stringname;
private Gendergender;
private Date birthday;
private byte[] portrait;
public Student(){}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId()
{
return id;
}
public void setId(intid)
{
this.id =id;
}
@Column(length=20,nullable=false)
public String getName()
{
return name;
}
public void setName(String name)
{
this.name =name;
}
@Enumerated(EnumType.STRING)
@Column(nullable=false)
public GendergetGender()
{
return gender;
}
public void setGender(Gender gender)
{
this.gender =gender;
}
@Temporal(TemporalType.DATE)
public DategetBirthday()
{
return birthday;
}
public void setBirthday(Date birthday)
{
this.birthday =birthday;
}
@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] getPortrait()
{
return portrait;
}
public void setPortrait(byte[]portrait)
{
this.portrait =portrait;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj)
{
if (this ==obj)
return true;
if (obj ==null)
return false;
if (getClass() !=obj.getClass())
return false;
Student other = (Student)obj;
if (id !=other.id)
return false;
return true;
}
@Override
public StringtoString()
{
return "Student [id=" + id + ", name=" + name + ", gender=" + gender
+ ", birthday=" + birthday + "]";
}
}
1.1、@Entity
标注@Entity的类,表示该类是一个可持久化的实体。该注解只有一个name属性,表示实体的名称,在执行JPQL时使用该名称;默认为实体类的非限定类名。
例如,指定实体名称为”Student”的代码为:@Entity(name=”Student”);在执行JPQL时,需要引用实体名“SELECTs FROM Student s”。
注意:
(1)由于使用类反射机制Class.newInstance方法创建实体时,会调用默认的构造方法,所以标注为@Entity的实体类要有一个无参数的构造方法;
(2)若要使实体可序列化,可以实现Serializable接口。虽然是可选的,但建议每个实体都实现Serializable接口,同时实现hashCode和equals方法;
1.2、@Table
@Table表示所映射表的属性,如下:
l name:实体所对应的表名,默认为实体名;
l catalog和schema:表示实体指定的目录名或数据库名,根据不同的数据库类型所有不同;
l uniqueContrains:实体关联的唯一约束条件,一个实体可以有多个唯一约束条件;
l UniqueConstraints:表示一个唯一性约束条件,一个唯一性约束条件可以包含多个字段,但这些字段不能同时相同。
1.3、@Id
一个实体类至少要有一个主键(PrimaryKey),能够标识为主键的属性类型有:
分类
类型
基本类型
byte、int、short、long、char
基本类型封装类
Byte、Integer、Short、Long、Character
大数值类型
BigInteger
字符串类型
String
时间日期类
java.util.Date、java.sql.Date
float和double类型及其对应的封装类不能作为主键,这是因为判断是否唯一是通过equals方法老判断的,浮点型的精度太大,不能够准确的匹配。
1.4、@GeneratedValue
@GeneratedValue:指定主键值的生成方式,需要配合@Id使用,属性如下:
l strategy
表示主键的生成策略,有四种类型AUTO、IDENTITY、SEQUENCE、TABLE;
l generator
为不同策略类型所对应的生成的规则名,随策略的不同而不同;
1.4.1、Auto
不同的数据库,自增主键的生成策略可能有所不同。在实体中,主键的生成策略默认为自增(Auto)。
1.4.2、Sequence
在Oracle中可以使用Sequence来生成自动主键,此时注解如下:
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="student_seq")
@SequenceGenerator(name="student_seq",sequenceName="student_sequence",initialValue=0,allocationSize=1)
public int getId()
{
return id;
}
@SequenceGenerator属性有:
l name:主键生成策略名,与@GeneratedValue中的generator值一致;
l sequenceName:数据库中创建的Sequence的名称;
l initialValue:主键初始值,默认为0;
l allocationSize:每次主键增加的大小,默认为50;
注意:@SequenceGenerator的作用范围为整个持久化单元(persistunit),也即可以在某一个实体中引用其他实体中声明的Sequence。
1.4.3、Identity
同Sequence一样,有些数据库支持Identity主键策略,如MicrosoftSQL Server。
1.4.4、Table
将当前主键的值单独保存到一个数据库的表中,主键的值每次都是从指定的表中查询出来获得。这种方法生成主键的策略可以适用于任何的数据库,不必担心与不同数据库不兼容造成的问题。
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="student_gen")
@TableGenerator(name="student_gen",
table="t_generator",
pkColumnName="gen_name",
valueColumnName="gen_value",
pkColumnValue="STUDENT_PK",
allocationSize=1)
public int getId()
{
return id;
}
l name:主键生成策略名,与@GeneratedValue中的generator值一致;
l table:数据库中主键生成策略的表名如t_generator;
l pkColumnName:t_generator的字段名gen_name;
l valueColumnName:t_generator字段gen_value当前所生成的值,它的值会累加;
l pkColumnValue:gen_name字段的值;
l initialValue:gen_value字段的初始值默认为0;
l allocationSize:gen_value字段每次增加的值。默认为50;
t_generator表结构如下:
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| gen_name | varchar(255) | YES | |NULL | |
| gen_value |int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+-------+
当每次向数据库插入实体数据时,都会首先更新t_generator表的gen_value字段,而gen_name字段则用于查询或更新条件,本身的值(pkColumnValue)并不会发生改变,如下
Hibernate:
select
gen_value
from
t_generator
where
gen_name = 'STUDENT_PK' forupdate
Hibernate:
update
t_generator
set
gen_value = ?
where
gen_value = ?
and gen_name = 'STUDENT_PK'
Hibernate:
insert
into
t_student
(birthday, gender, name,portrait, id)
values
(?, ?, ?, ?, ?)
1.4.5、复合主键
有时一个实体的主键可能同时为多个(复合主键),此时需要@Embeddable(嵌入式主键)来修饰主键类,如下
@Embeddable
public class StudentPK implements Serializable
{
private static final long serialVersionUID = 1L;
private Stringname;
private Stringemail;
public StudentPK()
{
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name =name;
}
public StringgetEmail()
{
return email;
}
public void setEmail(String email)
{
this.email =email;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((email ==null) ? 0 :email.hashCode());
result = prime * result + ((name ==null) ? 0 :name.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this ==obj)
return true;
if (obj ==null)
return false;
if (getClass() !=obj.getClass())
return false;
StudentPK other = (StudentPK)obj;
if (email ==null)
{
if (other.email !=null)
return false;
}
else
if (!email.equals(other.email))
return false;
if (name ==null)
{
if (other.name !=null)
return false;
}
else
if (!name.equals(other.name))
return false;
return true;
}
}
主键类必须满足以下要求:
l 必须实现Serializable接口;
l 必须有默认的public无参数构造方法;
l 必须覆盖equals和hashCode方法;
l 将嵌入式主键类使用@Embeddable标注,表示这是一个嵌入式类;
在实体类中,使用@Embeddable来标注主键,如下
@Entity
@Table(name="t_student")
public class Student implements Serializable
{
private static final long serialVersionUID = 1L;
private StudentPKid;
public Student(){}
@EmbeddedId
public StudentPKgetId()
{
return id;
}
public void setId(StudentPK id)
{
this.id =id;
}
/*
* ....
* */
}
1.5、@Column
@Column表示所映射表中的字段,属性如下:
l name:数据库表字段名;
l unique:表示该字段是否为唯一标识,默认为false。如果表中有一个字段为唯一标识,可以使用unique属性,也可以使用@Table中的@UniqueConstraint;
l length:表示字段的长度(当字段的类型为varchar时,才有效),默认为255;
l precision和scale:表示精度,但字段为double时,precision表示数值的总长度,scale表示小数点所占的位数;
l insertable:表示插入数据时,是否需要插入该字段的值;在保存实体时,持久化驱动默认使用全部成员属性映射的字段来构造INSET语句,如果不想让某个字段出现在insert语句中,可以设置insertable=false;
l updateable:表示更新数据时,是否需要更新该字段的值。insertable和updateable一般用于只读的属性;
l columnDefinition:定义表结构时,用于创建该字段的DDL,该属性特定于具体的数据库,不建议使用。
1.6、@Enumerated
如果需要将枚举类型成员属性映射到数据库,可以使用@Enumerated。枚举类型成员属性可以被映射为字符串形式(EnumType.STRING),也可以映射为枚举值的数据序号(EnumType.ORDINAL)。
如果使用STRING保存枚举值,虽然从数据库中查询数据时非常直观,能够清楚地看出该类型代表的意义。同时也会带来其他的问题,若枚举类型的定义发生改变,此时数据中的字符串将不能转换为枚举值,建议使用ORDINAL值。
1.7、@Temporal
@Temporal指定java.util.Date或java.util.Calendar类型成员属性与数据库类型date、time或timestamp的哪一种映射,缺省情况下,持久化驱动假定时间类型为timestamp。
1.8、@Lob
通常,可以在数据库中保存诸如图片、长文本类型的数据,这些数据一般是保存为Blob和Clob类型。
Blob和Clob类型的数据可以通过使用@Lob来标注,其中Clob(CharacterLarge Objects)类型是长字符串类型,映射为实体中的类型可以为char[]、Character[]或String类型。Blob(BinaryLarge Objects)类型是字节类型,映射为实体中的类型可以为byte[]、Byte[]或者实现了Serializable接口的类。
由于这两种类型的数据一般占用内存空间较大,所以通常使用懒加载的方式(配合@Basic使用)。
1.9、@Transient
JPA实现将属性和对应的Getter方法认为是可持久化的。如果实体中有属性并不需要持久化,可以使用@Transient。
1.10、可持久化类型
在JPA规范中,并不是所有的类型的属性都可以持久化的,下表列举了可映射为持久化的属性类型:
分类
类型
基本类型
byte、int、short、long、boolean、char、float、double
基本类型封装类
Byte、Integer、Short、Long、Boolean、Character、Float、Double
字节和字符数组
byte[]、Byte[]、char[]、Character[]
大数值类型
BigInteger、BigDecimal
字符串类型
String
时间日期类
java.util.Date、java.util.Calendar、java.sql.Date、java.sql.Time、java.sql.Timestamp
集合类
java.util.Collection、java.util.List、java.util.Set、java.util.Map
枚举类型
嵌入式
Entuty类型
对于可持久化的java类型中,即可以映射为基本数据类型,也可以映射为基本数据类型的封装类,那么选择哪种类型比较适合呢?
若字段可能存在空值,则建议映射为基本类型的封装类,否则将产生转换银异常,如空值转换为int值。
- JPA实体映射关系
- JPA实体基本映射
- JPA 实体映射
- JPA实体关系映射
- JPA实体多表映射
- JPA实体继承的映射
- JPA实体继承的映射
- JPA实体继承的映射
- JPA实体继承实体的映射策略
- JPA实体继承实体的映射策略
- JPA实体继承实体的映射策略
- JPA实体继承实体的映射策略
- JPA教程:JPA概述、JPA实体生命周期、JPA实体映射关系、JPA查询语言
- 传智播客--JPA的CRUD操作,映射实体
- JPA实体继承关系的映射策略
- JPA的CRUD操作,映射实体
- JPA实体关系映射之注释
- JPA实体关系映射之注释
- ViewController之间的block传值
- html 添加视频
- axis webservice调试
- Java内存管理和垃圾回收
- run模式可以启动,debug模式无法启动
- JPA 实体映射
- [leetcode]Majority Element C语言
- POJ 3122 Pie(二分)
- Scheme 语言概要(上)
- CODEVS 1021 玛丽卡 最短路模板题
- 手机淘宝构架演化实践
- uboot 引导kernel杂谈
- 【Qt】QThread::moveToThread
- Scheme 语言概要(下)