前面章节介绍了 JPA、OpenJPA 基础知识,以及准备 OpenJPA 学习环境。本章节将通过一个简单的入门实例介绍怎样使用 OpenJPA 去操作数据库。
入门 OpenJPA 实例的项目结构如下图:
上图中,persistence.xml 文件为 OpenJPA 的配置文件,指定 JPA 提供者、数据库配置、实体配置等。User 为实体类,OpenJpaHello 是一个可以直接运行的 Java 类(拥有 main 方法)。
下面配置了一个持久化单元名为“openJPA”的实例。配置信息如下:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> <persistence-unit name="openJPA" transaction-type="RESOURCE_LOCAL"> <!-- JPA提供者 --> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <!-- 声明实体类 --> <class>com.huangx.openjpa.hello.entity.User</class> <!-- 配置JPA数据库属性 --> <properties> <property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/openjpa_learn?useSSL=false& serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8"/> <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/> <property name="openjpa.ConnectionUserName" value="root"/> <property name="openjpa.ConnectionPassword" value="aaaaaa"/> <!-- 自动生成表 --> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> <!-- 不使用加载时强化和编译时强化,使用运行时Unenhanced --> <property name="openjpa.ClassLoadEnhancement" value="false" /> <property name="openjpa.DynamicEnhancementAgent" value="false" /> <property name="openjpa.RuntimeUnenhancedClasses" value="supported" /> </properties> </persistence-unit> </persistence>
由于 OpenJPA 的增强器(Enhancer)能够在运行时对系统性能进行优化,并且提高惰性加载的灵活性,是 OpenJPA 与 Hibernate 最大不同之处。增强器能够自动为持久化的类添加一些代码,这些代码能够帮助二进制的类实现持久化类所必需的一些特性。上面配置中,通过如下配置禁用加载时强化和编译时强化:
<!-- 不使用加载时强化和编译时强化,使用运行时Unenhanced --> <property name="openjpa.ClassLoadEnhancement" value="false" /> <property name="openjpa.DynamicEnhancementAgent" value="false" /> <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
如果不禁用加载时强化和编译时强化,运行程序将抛出如下错误信息:
Exception in thread "main" <openjpa-2.4.2-r422266:1777108 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "com.huangx.openjpa.hello.entity.User".
注意:在开发或者学习OpenJPA时可以禁用 OpenJPA 增强,在生成环境推荐开启增强功能,提供程序性能。
使用 @Entity(标记该类为一个实体)、@Table(指定实体映射的数据表名称)、@Id(声明一个ID字段)、@Column(声明一个数据表列)和 @GeneratedValue(指定主键自动生成策略)注解声明一个简单的实体类,实现和数据库表(users)进行 ORM 映射。代码如下:
import javax.persistence.*; @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String name; @Column private Integer age; // 忽略 get 和 set 方法 @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
下面将简单的介绍怎样使用 OpenJPA API 保存数据到数据库表。代码如下:
import com.huangx.openjpa.hello.entity.User; import com.huangx.openjpa.utils.DateUtils; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class OpenJpaHello { public static void main(String[] args) { // 创建 EntityManagerFactory EntityManagerFactory emf = Persistence.createEntityManagerFactory("openJPA"); // 创建 EntityManager EntityManager em = emf.createEntityManager(); // 创建实例类 User user = new User(); user.setName("Helen-" + DateUtils.getDate()); user.setAge(28); // 开启事务,写入数据到数据库 em.getTransaction().begin(); em.persist(user); em.getTransaction().commit(); // 关闭资源 em.close(); emf.close(); System.out.println("success!!!"); } }
运行客户端程序,输出结果如下:
54 openJPA WARN [main] openjpa.Runtime - The configuration property named "openjpa.ClassLoadEnhancement" was not recognized and will be ignored, although the name closely matches a valid property called "openjpa.PostLoadOnMerge". 137 openJPA INFO [main] openjpa.Runtime - Starting OpenJPA 2.4.2 255 openJPA INFO [main] openjpa.jdbc.JDBC - Using dictionary class "org.apache.openjpa.jdbc.sql.MySQLDictionary". 1010 openJPA INFO [main] openjpa.jdbc.JDBC - Connected to MySQL version 5.5 using JDBC driver MySQL Connector Java version mysql-connector-java-5.1.46 ( Revision: 9cc87a48e75c2d2e87c1a293b2862ce651cb256e ). 1349 openJPA WARN [main] openjpa.Enhance - Creating subclass for "[class com.huangx.openjpa.hello.entity.User]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead. success!!!
查看数据库 users 表,数据被写入到了数据库。