目录结构
下面为我的工程目录结构:
其中persistence.xml是必须的,
Maven依赖项
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>2.3.0</version>
</dependency>
<!--Servlet级别-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
<build>
<finalName>${artifactId}</finalName>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<includes>**/entities/*.class</includes>
<excludes>**/entities/XML*.class</excludes>
<addDefaultConstructor>true</addDefaultConstructor>
<enforcePropertyRestrictions>true</enforcePropertyRestrictions>
</configuration>
<executions>
<execution>
<id>enhancer</id>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
在pom.xml中添加相应的插件。
persistence.xml和orm.xml
persistence.xml数据源和属性较为全面的配置
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="TODS" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>ls.jpa.chapter.entities.Employee</class>
<!--自动加载所有实体-->
<!--<exclude-unlisted-classes>false</exclude-unlisted-classes>-->
<!--注解方式 or xml配置-->
<!--<mapping-file>META-INF/orm.xml</mapping-file>-->
<!--所有属性参考http://openjpa.apache.org/builds/2.2.1/apache-openjpa/docs/ref_guide_conf_openjpa.html-->
<properties>
<!--自动建表空间-->
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
<!--数据源-->
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/db_test"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="****"/>
<property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
<!--开启日志-->
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
<!--<property name="openjpa.Log" value="none"/>-->
<!--动态运行时-->
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm" />
<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
<!-- 启用缓存,并且设置缓存的容量为5000,并且禁用软引用容量 -->
<property name="openjpa.DataCache" value="true(CacheSize=5000, SoftReferenceSize=100)" />
<!-- 启用查询结果缓存,缓存的容量为1000,并且软引用的容量为100 -->
<property name="openjpa.QueryCache" value="true(CacheSize=5000, SoftReferenceSize=100)" />
<!-- 缓存的数据存储类型 -->
<property name="openjpa.QueryCompilationCache" value="true" />
<!-- 数据库连接工厂时的属性 QueryTimeout:JDBC驱动执行查询超时的时间,以秒为单位。 PrettyPrint:是否格式化输出SQL语句。 PrettyPrintLineLength:SQL每行输出的最大长度。 -->
<property name="openjpa.ConnectionFactoryProperties" value="PrettyPrint=true, PrettyPrintLineLength=100" />
<!-- 查询结果一次转化为对象的最多个数,相当于JDBC的结果集对象Statement.set FetchSize。默认为-1,表示所有的查询对象立即初始化;0表示使用JDBC驱动默认的数值 -->
<property name="openjpa.FetchBatchSize" value="-1" />
</properties>
</persistence-unit>
</persistence>
orm.xml对象-关联映射
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
version="2.0">
<entity class="ls.jpa.chapter.entities.Employee" name="Emp">
<table name="t_employee"/>
</entity>
</entity-mappings>
单元测试
首先建立实体类Employee:
import javax.persistence.*;
import java.io.Serializable;
/**
* @author Barudisshu
*/
@Entity
@Table(name = "t_employee")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "EmployeeSeqXX")
@SequenceGenerator(name = "EmployeeSeqXX", allocationSize = 1)
private int id;
private String name;
private long salary;
public Employee() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
}
建立对应服务类:
import javax.persistence.*;
import java.util.List;
/**
* @author Barudisshu
*/
public class EmployeeService {
protected EntityManager em;
public EmployeeService(EntityManager em) {
this.em = em;
}
public Employee createEmployee(int id, String name, long salary) {
Employee emp = new Employee();
emp.setId(id);
emp.setName(name);
emp.setSalary(salary);
Query query = em.createNativeQuery("INSERT INTO db_test.t_employee(id,name,salary) VALUES (?, ?, ?)");
query.setParameter(1, emp.getId());
query.setParameter(2, emp.getName());
query.setParameter(3, emp.getSalary());
int row = query.executeUpdate();
if (row < 1)
return null;
else
// em.merge(emp);
return emp;
}
public void removeEmployee(int id) {
Employee emp = findEmployee(id);
if (emp != null) {
em.remove(emp);
}
}
public Employee raiseEmployeeSalary(int id, long raise) {
Employee emp = em.find(Employee.class, id);
if (emp != null) {
emp.setSalary(emp.getSalary() + raise);
}
return emp;
}
public Employee findEmployee(int id) {
return em.find(Employee.class, id);
}
public List<Employee> findAllEmployees() {
TypedQuery<Employee> query = em.createQuery("select e from Emp e", Employee.class);
return query.getResultList();
}
}
单元测试类:
import ***;
public class EmployeeTest {
private static final Logger logger = Logger.getLogger(EmployeeTest.class);
private static final String PERSISTENCE_UNIT_NAME = "TODS";
private EntityManagerFactory emf;
private EntityManager em;
private EmployeeService service;
@Before
public void setUp() {
// Obtaining an entities manager
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
em = emf.createEntityManager();
service = new EmployeeService(em);
}
@Test
public void simpleTests() {
// Read the existing entries and write to console
TypedQuery<Employee> query = em.createQuery("select e from Emp e", Employee.class);
List<Employee> employeeList = query.getResultList();
// List employee name
logger.info("Entities: " + JSON.toJSON(employeeList));
logger.info("Size: " + employeeList.size());
// Simple transaction
em.getTransaction().begin();
Employee employee = new Employee();
employee.setName("Barudisshu");
employee.setSalary(3300);
em.persist(employee);
em.getTransaction().commit();
// Close the EM and EMF when done
em.close();
emf.close();
}
@Test
public void serviceTests() {
// Create and persist an employee
em.getTransaction().begin();
Employee emp = service.createEmployee(158, "John Doe", 45000);
em.getTransaction().commit();
logger.info("Persisted: " + emp);
// Find specific employee
emp = service.findEmployee(158);
logger.info("Found: " + emp);
// Find all employees
List<Employee> emps = service.findAllEmployees();
logger.info("Found all: " + JSON.toJSON(emps));
// Update the employee
em.getTransaction().begin();
emp = service.raiseEmployeeSalary(158, 1000);
em.getTransaction().commit();
logger.info("Updated: " + JSON.toJSON(emp));
// Remove an employee
em.getTransaction().begin();
service.removeEmployee(158);
em.getTransaction().commit();
logger.info("Remove employee 158");
// Close the EM and EMF when done
em.close();
emf.close();
}
}
注意以上代码EmployeeService类中的注释em.merge(emp);,理论上在Hibernate上运行是可以通过的,但在openJPA上会报:
The instance life cycle is in PNewState state and hence an existing non-default value for the identity field is not permitted. You either need to remove the @GeneratedValue annotation or modify the code to remove the initializer processing.
大意就是说执行merge()方法的时候我们设的值和@GeneratedValue自增的值有冲突,这明显只是EntityManager.persist()才会有的问题,EntityManager.merge()是合并的意思,在Hibernate中如果包含则合并,然而openJPA并没有这样做,不知道Apache组织理解错了游离态、瞬态、持久态的概念,还是故意要这样做的,貌似这是一个Bug,可以在http://issues.apache.org/jira/browse/OPENJPA-2074中看到。
另一方面,openJPA在Spring支持中貌似不够好,openJPA最新版本也只支持到Java EE6,一些Java EE7特性无法在Spring中显现。