JPA概述
JPA是独立于SQL ,基于JDBC之上的抽象层。所有类和注解都在javax.persistence包中。
JPA主要组件:
1.ORM,对象和数据库数据之间的映射
2.An entity manager API执行数据库相关操作,CRUD(Create, Read, Update, Delete)
3.JPQL(The Java Persistence Query Language) 用面向对象的查询语言查询数据
4.事务和锁机制
5.回调(Callbacks)和监听器(listeners)定制持久化生命周期逻辑
JPA2.0新特征:
1.基本数据类型(String, Integer, etc.)的集合和嵌入对象的集合可以映射到不同的表中。之前,你仅能映射实体的集合。
2.Map支持被扩展(Map映射),maps的keys和values可以是基本类型,实体,嵌入对象。
3.加入@OrderColumn注解维护持久化排序。
4.关系映射中父对象被移除,子对象被移除(Orphan removal的支持)。
5.悲观锁的支持。
6.引进新的Criteria API,基于面向对象方式的查询。
7.JPQL语法支持case expressions。
8.嵌入对象可以嵌入其他嵌入对象,并与之关系映射。
9.dot(.)导航语法被扩展,处理关系映射中嵌入对象,嵌入对象的嵌入对象。
10.新的缓存API被加入。
11.persistence.xml文件中一些属性被标准化,增加程序的可移植性。
我们先看一个简单的例子。
我的运行环境是 eclipse+mvn
1. 在 maven 插件中添加附件archetype-catalog.zip中的 local Archetype
2. 创建 maven project , Filter : weld ,选择 Artifact Id : jboss-javaee6-webapp, 该 archetype 可以快速创建 JavaEE6 项目,更多信息: http://seamframework.org/Documentation/CDIQuickstartForMavenUsers
3 . 填写 maven 坐标
4. 我们现在删除一些我们现在不需要的代码,删除org.example.myproject.controller,org.example.myproject.data,org.example.myproject.rest包,删除org.example.myproject.model.Member类,org.example.myproject.test.MemberRegistrationTest测试类。
5. 好了,现在我们需要创建我们自己的实体类
package org.example.myproject.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.NamedQuery; @Entity @NamedQuery(name="findAllBooks",query="select b from Book b") public class Book { @Id @GeneratedValue private Long id; @Column(nullable=false) private String title; private Float price; @Column(length=2000) private String description; private String isbn; private Integer nbOfPage; private Boolean illustrations; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public Integer getNbOfPage() { return nbOfPage; } public void setNbOfPage(Integer nbOfPage) { this.nbOfPage = nbOfPage; } public Boolean getIllustrations() { return illustrations; } public void setIllustrations(Boolean illustrations) { this.illustrations = illustrations; } }
还有我们的测试代码:
package org.example.myproject.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.sql.SQLException; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import org.example.myproject.model.Book; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class BookTest { private static EntityManagerFactory emf; private static EntityManager em; private static EntityTransaction tx; @BeforeClass public static void initEntityManager() throws Exception { emf = Persistence.createEntityManagerFactory("primary"); em = emf.createEntityManager(); } @AfterClass public static void closeEntityManager() throws SQLException { em.close(); emf.close(); } @Before public void initTransaction() { tx = em.getTransaction(); } @Test public void shouldCreateABook() throws Exception { // Creates an instance of book assertNotNull("EMF should not be null", emf); Book book = new Book(); book.setTitle("The Hitchhiker's Guide to the Galaxy"); book.setPrice(12.5F); book.setDescription("Science fiction comedy book"); book.setIsbn("1-84023-742-2"); book.setNbOfPage(354); book.setIllustrations(false); // Persists the book to the database tx.begin(); em.persist(book); tx.commit(); assertNotNull("ID should not be null", book.getId()); // Retrieves all the books from the database List<Book> books = em.createNamedQuery("findAllBooks").getResultList(); assertEquals(1, books.size()); } }
6. 我们现在要修改 persistence.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" 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"> <persistence-unit name="primary"> <!-- You can force a non-default JPA provider using one of these declarations --> <!-- <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> --> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>org.example.myproject.model.Book</class> <!-- jdbc/__default is the default data source in GlassFish --> <!-- A matching data source is added to JBoss AS by deploying the project file default-ds.xml <jta-data-source>jdbc/__default</jta-data-source>--> <properties> <!-- Properties for Hibernate (default provider for JBoss AS) --> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="false" /> <!-- Properties for EclipseLink (default provider for GlassFish) --> <property name="eclipselink.ddl-generation" value="drop-and-create-tables" /> <property name="eclipselink.logging.level" value="FINE" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/javaee6" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="" /> </properties> </persistence-unit> </persistence>
把 src/main/resources 下的 META-INF 目录 ( 包含 persistence.xml) 复制到 src/test/resources
目录下
记得要创建数据库 javaee6 ,改写你自己的用户名密码
7. 下一步就是要修改 pom.xml 了,添加依赖包坐标
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-commons-annotations</artifactId> <version>3.2.0.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.6.0.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.6.0.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.6</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.16</version> <scope>test</scope> </dependency>
并修改profile id为default的跳过测试配置值为false
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.4.3</version> <configuration> <skip>false</skip> </configuration> </plugin>
8. 运行 maven test 。就可以看到数据库中已经多了一张 book 表,并插入了值。