JPA

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压缩包里面都有)

 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标签就可以了


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值