什么是JPA:
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate、TopLink等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate、TopLink等ORM框架的基础上发展而来的,具有易于使用、伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring与EJB3.0的开发团队。着眼未来几年的技术走向,JPA作为ORM领域标准化整合者的目标应该不难实现。
JPA的总体思想和现有Hibernate、TopLink等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
ORM映射元数据
JPA支持XML和JDK 5.0注释(也可译作注解)两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。
Java持久化API用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者可以从繁琐的JDBC和SQL代码中解脱出来。
查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
提示: JPA不是一种新的ORM框架,他的出现只是用于规范现有的ORM技术,他不能取代现有的Hibernate、TopLink等ORM框架。相反,在采用JPA开发时,我们仍将使用到这些ORM框架,只是此时开发出来的应用不再依赖于某个持久化提供商。应用可以在不修改代码的情况下在任何JPA环境下运行,真正做到低耦合,可扩展的程序设计。
JPA工程
所需JAR包
Hiberante核心包(8个文件)
hibernate-distribution-3.3.1.GA
---------------------------------------------
hibernate3.jar
lib\bytecode\cglib\hibernate-cglib-repack-2.1_3.jar
lib\required\*.jar
Hiberante注解包(3个文件):hibernate-annotations-3.4.0.GA
------------------------------------------------------------------------------------
hibernate-annotations.jar
lib\ejb3-persistence.jar、hibernate-commons-annotations.jar
Hibernate针对JPA的实现包(3个文件):hibernate-entitymanager-3.4.0.GA
------------------------------------------------------------------------------------------------------
hibernate-entitymanager.jar
lib\test\log4j.jar、slf4j-log4j12.jar
JPA配置文件
JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的,配置模版如下:
<?xml version="1.0"?> <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_1_0.xsd" version="1.0"> <persistence-unit name="itcast" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="root"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
JPA实体类:
/**在实体bean中用注解@Entity来指定实体以让jpa知道生成数据库中的表*/ @Entity /**在实体类的前面用注解@Table(name="xx")指定生成表的名字*/ @Table(name = "t_person") public class Person implements Serializable { private Integer id; private String name; private Date birthday; private Gender gender = Gender.MAN;// 设置默认值 private String info; private byte[] file; private String imagePath; /**Table效率不高*/ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } /**在实体bean中用注解@Column(length,nullable,name)指定数据库中的表的字段的长度,是否为空即字段的名字*/ @Column(name = "person_name", nullable = true, length = 30) public String getName() { return name; } public void setName(String name) { this.name = name; } /**反射用,默认无参构造函数*/ public Person() { super(); } /**在实体类中用注解@Temporal(TemporalType.Date)指定生日的时间类型*/ @Column(name = "birthday", nullable = true) @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Column(length = 5, nullable = true) @Enumerated(EnumType.ORDINAL) /**@Enumerated(EmumType.STRING)注解指定枚举类型(保存到数据库中是字符串) @Enumerated(EnumType.ORDINAL)注解指定枚举类型(保存到数据库中是索引,从0开始) */ public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } /**@Lob声明属性对应的数据库字段为大文本类型,可以存放大的数据(文本和字节)*/ @Lob public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Lob /**是否把数据装载到内存中延迟初始化,第一次访问的时候在加载数据,一般用在大数据存放*/ @Basic(fetch=FetchType.LAZY) /**FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载*/ public byte[] getFile() { return file; } public void setFile(byte[] file) { this.file = file; } /**指定这个字段不跟数据库字段进行映射和关联*/ @Transient public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } public Person(String name) { super(); this.name = name; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + "]"; } }
实体引用枚举
public enum Gender { MAN, WOMEN }
JPA测试类
/** * jpa四种状态 * 1.new 新建 * 2.托管 * 3.游离(脱管) * 4.删除 * */ public class PersonTest { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Test public void test() { fail("Not yet implemented"); } /** * 增加数据 */ @Test public void save() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); /** 读取数据不要开启事务,只要有更改数据的动作才需要开启事务*/ em.getTransaction().begin(); //new 新建 new一个实例 Person p=new Person("张三"); //持久化 em.persist(p);////插入 em.getTransaction().commit(); em.close(); factory.close(); } /** * 删除数据 */ @Test public void remove() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person p=em.find(Person.class, 1); em.remove(p);//删除(注意有外键约束时,需要先解除外键约束才能删除) em.getTransaction().commit(); em.close(); factory.close(); } /** * 更新数据:方法一 */ @Test public void updatePerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person p=em.find(Person.class, 2); p.setName("老张test");//(1).跟事务关联在一起了(2)对象处于托管状态,可以直接保存到数据库 em.getTransaction().commit(); em.refresh(p);//进行数据库刷新,拿出最新的数据 System.out.println(p); em.close(); factory.close(); } /** * 更新数据:方法二 */ @Test public void updatePerson2() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person p=em.find(Person.class, 2); em.clear();////把事务管理器中的所有实体变成游离状态 p.setName("老张");//现在还是不可以,实体还是处于游离状态 em.merge(p);//把游离状态中的实体bean同步到数据库 em.getTransaction().commit(); em.close(); factory.close(); } /** * 查看数据:方法一 */ @Test public void getPerson() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); Person p=em.find(Person.class, 1); System.out.println(p);//如果找不到,返回null值 em.close(); factory.close(); } /** * 查看数据:方法二 */ @Test public void getPerson2() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); Person p=em.getReference(Person.class, 0);//1.没有值不出现异常 System.out.println(p);//获取属性值时,如果找不到,出现异常 //2出现异常 em.close(); factory.close(); } /** * 查看数据:返回结果集 */ @Test public void queryAll() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query=em.createQuery("select o from Person o"); List<Person> list=query.getResultList(); for(Person p:list){ System.out.println(p); } em.close(); factory.close(); } /** * 查看数据:返回单条数据 */ @Test public void querySigle() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); Query query=em.createQuery("select o from Person o where o.id=?1");//必须有select o,id=等于后面不要直接写值以免sql注入 query.setParameter(1, 2); /** * (1)匿名查询用:id (2)未参数查询?1即:where o.id=?1//指明?的值从索引1开始 */ Person p=(Person) query.getSingleResult();//获取单条记录 System.out.println(p); em.close(); factory.close(); } /** * 查询删除 */ @Test public void queryDelete() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query=em.createQuery("delete from Person o where o.id=?1"); query.setParameter(1, 2);//位置参数 int i=query.executeUpdate(); System.out.println("受影响的行数 :"+i); em.close(); factory.close(); } /** * 查询更新 */ @Test public void queryUpdate() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("itcast"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query=em.createQuery("update Person o set o.name=:name where o.id=:id"); query.setParameter("name", "五五");//匿名参数 query.setParameter("id", 3); int i=query.executeUpdate(); System.out.println("受影响的行数 :"+i); em.close(); factory.close(); } }
JPA总结
首先,JPA不是ORM框架,而是SUN官方提出的JAVA持久化规范。JPA整合了现有的Hibernate、TopLink等ORM框架,具有易于使用、伸缩性
强等优点。下面我们就来学习关于JPA的知识。
1. JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的,配置模版可见hibernate-entitymanager开发包
2. JPA ORM映射元素数据有XML和注解两种方式,这里我们学习基于注解的方式,那么我们来谈谈JPA有哪些常用的注解
1) 在实体bean中用注解@Entity来指定实体以让jpa知道生成数据库中的表
2) 在实体bean中用注解@Column(length,nullable,name)指定数据库中的表的字段的长度,是否为空即字段的名字
3) 在实体类的前面用注解@Table(name="xx")指定生成表的名字
4) 在实体类中用注解@Temporal(TemporalType.Date)指定生日的时间类型
5) @Enumerated(EmumType.STRING//保存到数据库中是索引还是字符串)注解指定枚举类型
6) @Lob声明属性对应的数据库字段为大文本类型,可以存放大的数据(文本和字节)
7) @Transient不成为持久化字段及不跟数据库中的字段形成映射
8) @Basic(fetch=FetchType.LAZY)//是否把数据装载到内存中延迟初始化,第一次访问的时候在加载数据,一般用在大数据存放
9) @Embeddable指定联合组键
3. JPA的增删改查:
1) 读取数据不要开启事务,只要有更改数据的动作才需要开启事务
2) 增加数据:em.persist(new Person("老黎"));//插入
3) 删除数据:em.remove(person); //删除(注意有外键约束时,需要先解除外键约束才能删除)
4) 更新数据:
方法一:Person person = em.find(Person.class,1);
person.setName("老黎");(1).跟事务关联在一起了(2)对象处于托管状态
方法二:Person person = em.find(Person.class,1);
em.clear();//把事务管理器中的所有实体变成游离状态
person.setName("老黎");//现在还是不可以,实体还是处于游离状态
em.merge(person);//把游离状态中的实体bean同步到数据库
说明:本人于ITEYE创建于2014年,现转移到CSDN