JPA的理解
JPA的总体思想和现有hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
- ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
- JPA的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
- 查询语言JPQL,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
JPA 实体生命周期理解
jpa 实体生命周期有四种状态
- New:瞬时对象,尚未有id,还未和Persistence Context建立关联的对象。
- Managed:持久化受管对象,有id值,已经和Persistence Context建立了关联的对象。
- Datached:游离态离线对象,有id值,但没有和Persistence Context建立关联的对象。
- Removed:删除的对象,有id值,尚且和Persistence Context有关联,但是已经准备好从数据库中删除
Managed状态下的数据保存,更新以及删除数据下的Removed状态,数据都不会立即更新到数据库,只有当你事务提交或者em.flush(),才会立即更新到数据库。
Datached的状态,可以调用em.merge()方法,这个方法会根据实体类的id来更新数据库数据,这时实体类变成了Managed状态。
四种状态总结:
状态名 | 作为java对象存在 | 在实体管理器中存在 | 在数据库存在 |
---|---|---|---|
New | yes | no | no |
Managed | yes | yes | no |
Datached | no | no | no |
Removed | yes | yes | no |
@Transactional
public void save(){
//New 状态
Task t = new Task();
t.setTaskName("task" + new Date().getTime());
t.setCreateTime(new Date());
//Managed状态
em.persist(t); //实体类t已经有id t.getId();
t.setTaskName("kkk"); //更新任务名称,这时,如果提交事务,则直接将kkk更新到数据库
//Detached状态 事务提交或者调用em.clear都直接将实体任务状态变为Detached
em.clear();
t.setTaskName("kkk"); //更新数据不会更新到数据库
//Removed状态
em.remove(t);
}
JPA 实体管理器
实体管理器(EntityManager)用于管理系统中的实体,它是实体与数据库之间的桥梁,通过调用实体管理器的相关方法可以把实体持久化到数据库中,同时也可以把数据库中的记录打包成实体对象。
JPA的persistence.xml文件
persistence.xml 是JPA的持久化配置文件,用来映射PU(Persist Unit)的。作用是映射表和类,里面也可以配置数据库连接信息
https://www.cnblogs.com/luxh/archive/2012/05/24/2516282.html
https://www.cnblogs.com/116970u/p/11584418.html
注意:配置参数hibernate.hbm2ddl.auto 各个取值的含义
validate update create create-drop
这几个参数的作用主要用于:自动创建 更新 验证数据库表结构
如果不是此方面的需求取none
validate:加载hibernate时,验证创建数据库表结构
create:每次加载hibernate,重新创建数据库表结构,这就是导致数据库表结构丢失的原因
create-drop:加载hibernate时创建,退出是删除表结构
update:加载hibernate自动更新数据库结构
列注解
当将Java bean映射到实体时,可以使用注解 @Column 表示物理数据库列的特定特征。
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
// 设置列值是否具有唯一性,默认不唯一
boolean unique() default false;
// 设置列是否允许为空,默认允许为空
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
// 声明对应数据库列类型
String columnDefinition() default "";
String table() default "";
// 设置字段长度
int length() default 255;
// 设置字段精度
int precision() default 0;
// 设置字段尺度
int scale() default 0;
}
参数columnDefinition
columnDefinition = “VARCHAR(40)”
使用name属性设置对应表字段
默认情况下,JPA使用字段名作为数据库表列名。可以使用name属性来设置列名称。
@Column(name = "sal")
private long salary; // 表明当前字段与数据表sal映射
使用length字段设置字段长度
使用JPA,我们可以设置字段的列长度。例如,当将字符串字段映射到VARCHAR时,我们可以在@Column 注释中设置VARCHAR长度。
@Column(length=40)
private String name; // 字段name varchar(40)
设置列精度范围
当将Java float或double值映射到数据库表列时,我们可以设置数字类型列的精度尺度。
以下代码将浮点值映射到具有精度8和尺度2的数据库表列。
@Column(precision=8, scale=2)
private float hourlyRate;
使用@Transient注释标记该字段不映射数据库字段
@Transient
private String convertedName;
此时,在对象关系映射时,字段convertedName不参与,数据表中没有字段与之对应。