1.JPA,java persisitence API,JPA通过JDK5.0注解-关系表的映射关系,并将运行期的实体对象持久化到数据库中,JPA是JavaEEE中的标准。JPA标准只提供了一套规范,需要有JPA的具体实现,Hibernate实现了JPA2.0标准,
所以我们在用JPA的时候,其实用的是Hibernate提供了JPA2.0规范的实现。JPA还有其他实现,比如OpenJPA,各个JPA的实现在使用细节上有一些不同,使用时需要注意;
2.JPA和Hibernate对比
1.JPA只是hibernate的一个子集,(支持JPA只是hibernate中的一个功能)
2.hibernate在对象状态,对象映射,对象关系,查询语句上和JPA80%都雷同
3.hibernate本身更依赖XML配置,而JPA完全使用Annotation实现
4.hibernate的API和JPA有一些区别(关键对象,对象方法)
3.JPA环境搭建
导入jpa的包以及hibernate需要的包,数据库驱动包(hibernate压缩包里面都有)
1.@Entity:标在类上,标明当前实体类是需要JPA管理的一个实体对象,类似于<class>
2.@Table:标在类上,标明当前实体类在数据库中对应的表,类似于<class>元素的table属性
3.配置属性(默认情况下,JPA会管理所有的属性,要规范属性,可以在字段上,也可以在getter方法)
4.@Id:标明当前属性是OID,类似<id>
5.@GeneratedValue:标明当前OID使用的主键生成方式,类似<generator>
6.@Column:标明当前属性对应的列,类似<property>的column
7.@Temporal:标明当前属性的日期类型
8.@Transient标签:设置一个字段不需要持久
getTransacton:得到事务对象,并调用begin方法开启事务
persist:持久化对象
find:得到对象相当于get方法
merge:修改对象,相当于update方法
调用Query对象的getResultList方法进行查询
session jpa
save: persist:persist方法必须运行在事务中
update: merge:merge方法必须运行在事务中
saveOrUpdate: merge:merge方法可以把临时对象或者有利对象都变成持久化对象
delete remove:remove方法必须运行在事务中
get: find:find返回对象类型不是Object
load: getReference:使用延迟加载
getTransaction: getTransace:得到的对象是EntityTransaction
createQuery: createQuery:
clear: clear:
evict detach:把一个指定的持久化对象变成游离对象
close: close:
单向的many2one:
1.@JoinColumn:相当于在many-to-one元素中的column
2.默认情况下,得many方,JPA会直接使用LEFT JOIN把one方查询出来,相当于没有延迟加载
3,@ManyToOne(fetch=FetchType.LAZY)
@Fetch(FetchMode.SELECT)
manytoone标签上的fetch属性代表是否延迟加载,默认是FetchType.EAGER如果使用延迟加载FetchType.LAZY
fetch标签代表怎么去拿关联的对象,默认情况使用left join直接把many方对应的one方拿到也可以设置为select,使用两条SQL分别加载many和one;
组件关系映射注解:
1.悲观锁
select * from employee for update可以阻止,除了select之外的其他SQL(FOR UPDATE,DML,LOCK IN SHARE MODE)
select *from employee lock in share mode可以阻止:DML FOR UPDATE,LOCK IN SHARE MODE
在JPA中使用悲观锁
em.find(Class,id,LockModeType)
LockModeType一般有两种方式:
1.PESSIMISITIC_READ:LOCK IN SHARE MODE:会通过造成死锁来阻止并发事务执行
2.PESSIMISTIC_WRITE:SELECT FOR UPDATE:会延迟另一个事务的执行(一般使用这种)
2.乐观锁
在对象中添加一个version属性,在上面添加@version标签就可以了
所以我们在用JPA的时候,其实用的是Hibernate提供了JPA2.0规范的实现。JPA还有其他实现,比如OpenJPA,各个JPA的实现在使用细节上有一些不同,使用时需要注意;
2.JPA和Hibernate对比
1.JPA只是hibernate的一个子集,(支持JPA只是hibernate中的一个功能)
2.hibernate在对象状态,对象映射,对象关系,查询语句上和JPA80%都雷同
3.hibernate本身更依赖XML配置,而JPA完全使用Annotation实现
4.hibernate的API和JPA有一些区别(关键对象,对象方法)
3.JPA环境搭建
导入jpa的包以及hibernate需要的包,数据库驱动包(hibernate压缩包里面都有)
JPA配置:persistence.xml文件,放于classpath下META-INF(自创的文件夹)/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<!-- persistence-unit持久化单元,对应看hibernate的sessionFactory,注意必须写name属性 -->
<persistence-unit name="jpa">
<!-- 默认情况下,JPA会自动在当前的classpath里面所有的类型中去发现@Entity标签的类,并自动吧这些类作为JPA管理的类型 -->
<properties>
<!-- 使用hibernate实现的JPA,在配置文件里面,有很多hibernate的配置项都可以使用
这个时候,如果用hibernate的配置项前面要写hibernate. -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="javax.persistence.jdbc.dirver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.show_sql" value="true"/>
<property name="javax.persistence.validation.mode" value="auto"/>
</properties>
</persistence-unit>
</persistence>
4.创建Employee对象,并添加注释
1.@Entity:标在类上,标明当前实体类是需要JPA管理的一个实体对象,类似于<class>
2.@Table:标在类上,标明当前实体类在数据库中对应的表,类似于<class>元素的table属性
3.配置属性(默认情况下,JPA会管理所有的属性,要规范属性,可以在字段上,也可以在getter方法)
4.@Id:标明当前属性是OID,类似<id>
5.@GeneratedValue:标明当前OID使用的主键生成方式,类似<generator>
6.@Column:标明当前属性对应的列,类似<property>的column
7.@Temporal:标明当前属性的日期类型
8.@Transient标签:设置一个字段不需要持久
9.@Lob:设置text类型,相当于hibernate<property type="text">
import javax.persistence.TemporalType;
//name属性代表类的简写名称,如果不写,默认为类名
@Entity
//table标签代表对应的表名----》class.table
@Table(name="employee")
public class Employee {
@Id
//GeneratedValue代表字段的值生成策略,一般情况下需要配置一个strategy(生成策略)
//GeneratedType.IDENTITY:<generator class="identity">
//GeneratedType.TABLE:<generator class="TableGenerator"/>
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
//JPA里面,默认情况下所有的属性都是需要持久化的;
@Column(name="username")
private String name;
private Integer age;
//Temporal这个标签专门用来处理日期
@Temporal(TemporalType.DATE)
private Date hireDate;
//省略set/get方法
5.API使用
1.JPA框架的启动
创建EntityManagerUtil
使用Persistance.createEntityManagerFactory("jpa")创建EntityManagerFactory
EntityManagerFactory类似SessionFactory,通过创建createEntityManager方法创建EntityManager
EntityManager类似Session,实体类的持久化方法有EntityManager提供
public class JPAUtil {
private static final JPAUtil instance=new JPAUtil();
//EntityManagerFactory是用来生成EntityManager(实体管理对象)---->session
//EntityManagerFactory---->sessionFactory
private EntityManagerFactory emFactory;
private JPAUtil(){
//启动框架,读取配置文件
//使用createEntityManagerFactory就可以
//从classpath下的META-INF文件夹中加载persistence.xml
//使用改名字对应的配置项去创建一个EntityManagerFactory
emFactory=Persistence.createEntityManagerFactory("jpa");
}
public static JPAUtil getInstance(){
return instance;
}
public EntityManager entityManager(){
return emFactory.createEntityManager();
}
}
2.完成CRUD
getTransacton:得到事务对象,并调用begin方法开启事务
persist:持久化对象
find:得到对象相当于get方法
merge:修改对象,相当于update方法
调用Query对象的getResultList方法进行查询
remove:删除一个对象,相当于delete方法
public class EmployeeDAOImpl implements IEmployeeDAO {
@Override
public void save(Employee e) {
EntityManager em=JPAUtil.getInstance().entityManager();
//开启事务
em.getTransaction().begin();
em.persist(e);//持久化对象
//提交对象
em.getTransaction().commit();
em.close();
}
@Override
public Employee get(Long id) {
EntityManager em=JPAUtil.getInstance().entityManager();
Employee e=em.find(Employee.class, id);
return e;
}
@Override
public void update(Employee e) {
EntityManager em=JPAUtil.getInstance().entityManager();
em.getTransaction().begin();
//更新对象
em.merge(e);
em.getTransaction().commit();
em.close();
}
@Override
public void delete(Long id) {
EntityManager em=JPAUtil.getInstance().entityManager();
em.getTransaction().begin();
Employee e=em.find(Employee.class,id);
//将持久化对象转为删除状态对象
//类似于session.delete()方法,但是remove方法只能作用域持久化对象
em.remove(e);
em.getTransaction().commit();
em.close();
}
@Override
public List<Employee> list() {
EntityManager em=JPAUtil.getInstance().entityManager();
//在JPA中,查询语句叫做JPQL,JPQL语法和使用方式上和HQL 90%相似
//List<Employee> e=em.createQuery("Select e from Employee e").getResultList();
List<Employee> es=em.createQuery("Select e from Employee e",Employee.class).getResultList();
em.close();
return es;
}
}
public class EmployeeDAOTest {
private IEmployeeDAO dao;
public EmployeeDAOTest(){
dao=new EmployeeDAOImpl();
}
@Test
public void testSave(){
Employee e=new Employee();
e.setAge(19);
e.setHireDate(new Date());
e.setName("xiaomi");
dao.save(e);
}
@Test
public void testGet(){
Employee e=dao.get(1L);
System.out.println(e);
}
@Test
public void testUpdate(){
Employee e=dao.get(1L);
e.setName("update");
dao.update(e);
}
@Test
public void testDelete(){
dao.delete(1L);
}
@Test
public void testQuery(){
List<Employee> es=dao.list();
System.out.println(es);
}
}
EntityManager方法对比:
session jpa
save: persist:persist方法必须运行在事务中
update: merge:merge方法必须运行在事务中
saveOrUpdate: merge:merge方法可以把临时对象或者有利对象都变成持久化对象
delete remove:remove方法必须运行在事务中
get: find:find返回对象类型不是Object
load: getReference:使用延迟加载
getTransaction: getTransace:得到的对象是EntityTransaction
createQuery: createQuery:
clear: clear:
evict detach:把一个指定的持久化对象变成游离对象
close: close:
单向的many2one:
1.@JoinColumn:相当于在many-to-one元素中的column
2.默认情况下,得many方,JPA会直接使用LEFT JOIN把one方查询出来,相当于没有延迟加载
3,@ManyToOne(fetch=FetchType.LAZY)
@Fetch(FetchMode.SELECT)
manytoone标签上的fetch属性代表是否延迟加载,默认是FetchType.EAGER如果使用延迟加载FetchType.LAZY
fetch标签代表怎么去拿关联的对象,默认情况使用left join直接把many方对应的one方拿到也可以设置为select,使用两条SQL分别加载many和one;
组件关系映射注解:
@Entity
public class Company {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
private Address address;
@AttributeOverrides({
@AttributeOverride(name="city",column=@Column(name="REG_CITY")),
@AttributeOverride(name="provice",column=@Column(name="REG_PROVICE")),
@AttributeOverride(name="street",column=@Column(name="REG_STREET"))
})
private Address regAddress;
//省略set/get方法
@Embeddable
public class Address {
private String provice;
private String city;
private String street;
JPA中的锁
1.悲观锁
select * from employee for update可以阻止,除了select之外的其他SQL(FOR UPDATE,DML,LOCK IN SHARE MODE)
select *from employee lock in share mode可以阻止:DML FOR UPDATE,LOCK IN SHARE MODE
在JPA中使用悲观锁
em.find(Class,id,LockModeType)
LockModeType一般有两种方式:
1.PESSIMISITIC_READ:LOCK IN SHARE MODE:会通过造成死锁来阻止并发事务执行
2.PESSIMISTIC_WRITE:SELECT FOR UPDATE:会延迟另一个事务的执行(一般使用这种)
2.乐观锁
在对象中添加一个version属性,在上面添加@version标签就可以了