JPA(Java Persistence API)为Java开发人员提供一种对象/关系映射工具以管理Java应用程序中的关系数据。JPA包含三个部分:
JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用的对象持久化的开发工作;其二,Sun希望整合对ORM技术,实现天下归一。JPA时一种持久化规范,其具体实现可以是Hibernate、TopLink,JDO等ORM框架,开发人员只需要根据JPA规范开发,而不是针对某个ORM框架,降低了耦合性。
JPA可以脱离容器运行,既可以在J2SE和J2EE环境运行,先动手试试:
这里使用hibernate作为实现orm框架,需要jar包如下:
hibernate-distribution核心包下的 hibernate3.jar, lib\bytecode\cglib\hibernate-cglib-repack.jar, lib\required\*.jar hibernate-annotations注解包: hibernate-annotations.jar, lib\ejb3-persistence.jar, hibernate-commons-annotation.jar hibernate-entitymanager对JPA的实现包: hibernate-entitymanager.jar, lib\test\log4j.jar,slf4j-log4j12.jar
<?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_1_0.xsd" version="1.0">
<persistence-unit name="JPA" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name = "hibernate.connection.driver_class" value = "com.mysql.jdbc.Driver"/>
<property name = "hibernate.connection.url" value = "jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8"/>
<property name = "hibernate.connection.username" value = "root"/><property name = "hibernate.connection.password" value = "root"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
@Entity // 所有实体类必须标示为javax.persistence.Entity
public class Person {
private Integer id;
private String name;
private Date birthday;//1988-02-01
private Gender gender=Gender.MAN;
private String info;
private Byte[] file;
private String imagePathString;
//必须有无参构造方法
public Person(){
}
public Person(String name){
this.name=name;
}
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
@Column(length=10,nullable=false)
public String getName() {
return name;
}
@Temporal(TemporalType.DATE)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Enumerated(EnumType.STRING)//将索引值保存进数据库
@Column(length=5,nullable=false) //设置长度,是否为null
public Gender getGender() {
return gender;
}
@Lob //大数据字段的说明,用在String上面是个大文本类型
public String getInfo() {
return info;
}
@Lob //大数据字段说明,用在这里是存放二进制数据的类型
@Basic(fetch=FetchType.LAZY) //延迟加载,当访问此属性的get方法时才会从数据库加载到内存,此时必须保证em处于打开状态,否则会有延迟加载错误。
public Byte[] getFile() {
return file;
}
@Transient //此属性不成为持久化字段
public String getImagePathString() {
return imagePathString;
}
// setter方法
}
枚举类
public enum Gender { MAN,WOMAN }
public class TestPersonCRUD { private static EntityManagerFactory fac; private EntityManager em; @BeforeClass public static void setUpBeforeClass() throws Exception { // 根据persistence.xml的配置规则,如设为create,每次加载hibernate时都会重建数据库 fac = Persistence.createEntityManagerFactory("test"); } @Before public void beforeTest() { em = fac.createEntityManager(); } @Test public void test() { test_save(); test_find(); test_update(); test_delete(); } public void test_save() { // 此时数据库表已经建立,若没有表,很可能是实体的注解出错了。 em.getTransaction().begin();// 开启事务 Person person = new Person("lzz"); person.setBirthday(new Date()); em.persist(person); em.getTransaction().commit();// 提交事务 } public void test_find() { // 读取不用开启事务 // 1为主键值,不错在则返回null Person p1 = em.find(Person.class, 1); assertEquals("lzz", p1.getName()); // 延迟初始化,不会立刻从数据库得到记录,只是得到一个代理对象 Person p2 = em.getReference(Person.class, 2); assertNotNull(p2); try { // 当我们访问这个代理对象的属性时,才从数据库得到记录,此时必须保证entityManager是开着的,否则出现延迟加载例外。 // 此时若访问时,不存在该实体则抛出例外EntityNotFoundException assertNull(p2.getName()); } catch(Exception e) { assertEquals(EntityNotFoundException.class, e.getClass()); } Person p3 = em.getReference(Person.class, 1); assertEquals("lzz", p3.getName()); } public void test_update() { em.getTransaction().begin(); Person p = em.find(Person.class, 1); p.setName("new"); em.getTransaction().commit(); Person np = em.find(Person.class, 1); assertEquals("new", np.getName()); } public void test_delete() { em.getTransaction().begin(); Person p = em.find(Person.class, 1); em.remove(p); em.getTransaction().commit(); Person dp = em.find(Person.class, 1); assertNull(dp); } @After public void afterTest() { em.close(); } @AfterClass public static void tearDownAfterClass() { fac.close(); } }