首页 > 代码库 > openJPA试水

openJPA试水

目录结构

下面为我的工程目录结构:

目录结构

其中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="http://www.mamicode.com/buildSchema(ForeignKeys=true)"/>
            <!--数据源-->
            <property name="openjpa.ConnectionURL" value="http://www.mamicode.com/jdbc:mysql://localhost:3306/db_test"/>
            <property name="openjpa.ConnectionUserName" value="http://www.mamicode.com/root"/>
            <property name="openjpa.ConnectionPassword" value="http://www.mamicode.com/****"/>
            <property name="openjpa.ConnectionDriverName" value="http://www.mamicode.com/com.mysql.jdbc.Driver"/>
            <!--开启日志-->
            <property name="openjpa.Log" value="http://www.mamicode.com/DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
            <!--<property name="openjpa.Log" value="http://www.mamicode.com/none"/>-->
            <!--动态运行时-->
            <property name="openjpa.DynamicEnhancementAgent" value="http://www.mamicode.com/false"/>
            <property name="openjpa.RemoteCommitProvider" value="http://www.mamicode.com/sjvm" />
            <property name="openjpa.RuntimeUnenhancedClasses" value="http://www.mamicode.com/supported"/>
            <!-- 启用缓存,并且设置缓存的容量为5000,并且禁用软引用容量 -->
            <property name="openjpa.DataCache" value="http://www.mamicode.com/true(CacheSize=5000, SoftReferenceSize=100)" />
            <!-- 启用查询结果缓存,缓存的容量为1000,并且软引用的容量为100 -->
            <property name="openjpa.QueryCache" value="http://www.mamicode.com/true(CacheSize=5000, SoftReferenceSize=100)" />
            <!-- 缓存的数据存储类型 -->
            <property name="openjpa.QueryCompilationCache" value="http://www.mamicode.com/true" />
            <!-- 数据库连接工厂时的属性 QueryTimeout:JDBC驱动执行查询超时的时间,以秒为单位。 PrettyPrint:是否格式化输出SQL语句。 PrettyPrintLineLength:SQL每行输出的最大长度。 -->
            <property name="openjpa.ConnectionFactoryProperties" value="http://www.mamicode.com/PrettyPrint=true, PrettyPrintLineLength=100" />
            <!-- 查询结果一次转化为对象的最多个数,相当于JDBC的结果集对象Statement.set FetchSize。默认为-1,表示所有的查询对象立即初始化;0表示使用JDBC驱动默认的数值 -->
            <property name="openjpa.FetchBatchSize" value="http://www.mamicode.com/-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中显现。





openJPA试水