Search code examples
javaspringjpaspring-data-jpaopenjpa

How to connect OpenJPA, Spring and PostgreSQL?


I'm trying to connect my PostgreSQL db with OpenJPA and Spring.

Here is my Spring Context file. It contains MVC part and TX.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:ctx="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <ctx:annotation-config/>
    <ctx:component-scan base-package="de.alex.web.pag"/>
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="pagPU"/>
        <property name="persistenceXmlLocation" value="/META-INF/persistence.xml"/>
        <property name="jpaVendorAdapter" ref="openJpaVendorAdapter"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/box"/>
        <property name="username" value="postgres"/>
        <property name="password" value="bob"/>
    </bean>

    <bean id="openJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
        <property name="showSql" value="true"/>
        <property name="generateDdl" value="true"/>
        <property name="database" value="POSTGRESQL"/>
        <property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.PostgresDictionary"/>
    </bean>
</beans>

Here is my persistence.xml in the /properties/META-INF/ folder:

<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_2_0.xsd"
             version="2.0">

    <persistence-unit name="pagPU" transaction-type="RESOURCE_LOCAL">

        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>

        <class>de.alex.web.pag.entity.Category</class>
        <class>de.alex.web.pag.entity.Order</class>
        <class>de.alex.web.pag.entity.Product</class>

        <properties>
            <property name="openjpa.ConnectionURL" value="jdbc:postgresql://localhost:5432/box"/>
            <property name="openjpa.jdbc.DBDictionary" value="postgres"/>
            <property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver"/>
            <property name="openjpa.ConnectionUserName" value="postgres"/>
            <property name="openjpa.ConnectionPassword" value="bob"/>
            <property name="openjpa.Log" value="SQL=TRACE"/>
        </properties>
    </persistence-unit>
</persistence>

When I try to run this simple script in my IDE I receive this exception:

[2014-09-26 17:16:43] java.lang.RuntimeException: <openjpa-2.3.0-r422266:1540826 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: An error occurred while parsing the query filter "select c from Category c where c.id = 1". Error message: The name "Category" is not a recognized entity or identifier. Known entity names: []
    at org.apache.openjpa.kernel.exps.AbstractExpressionBuilder.parseException(AbstractExpressionBuilder.java:119)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getClassMetaData(JPQLExpressionBuilder.java:197)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.resolveClassMetaData(JPQLExpressionBuilder.java:167)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:242)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:212)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateType(JPQLExpressionBuilder.java:205)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.access$200(JPQLExpressionBuilder.java:80)
    at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder$ParsedJPQL.populate(JPQLExpressionBuilder.java:2428)
    at org.apache.openjpa.kernel.jpql.JPQLParser.populate(JPQLParser.java:61)
    at org.apache.openjpa.kernel.ExpressionStoreQuery.populateFromCompilation(ExpressionStoreQuery.java:162)
    at org.apache.openjpa.kernel.QueryImpl.newCompilation(QueryImpl.java:673)
    at org.apache.openjpa.kernel.QueryImpl.compilationFromCache(QueryImpl.java:654)
    at org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:620)
    at org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:682)
    at org.apache.openjpa.kernel.QueryImpl.compile(QueryImpl.java:589)
    at org.apache.openjpa.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:997)
    at org.apache.openjpa.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:979)
    at org.apache.openjpa.persistence.EntityManagerImpl.createQuery(EntityManagerImpl.java:102)
    in RemoteEntityManagerImpl.createQuery(RemoteEntityManagerImpl.java:39)
    in RemoteUtil.executeWithClassLoader(RemoteUtil.java:167)
    in RemoteUtil$2$1.invoke(RemoteUtil.java:102)
    at com.sun.proxy.$Proxy151.createQuery(Unknown Source)
    in JpaEngine.createQuery(JpaEngine.java:104)

Seems I missed something important when I was configuring Spring context or JPA context.

UPDATE

My entity class:

@Entity
@Table(name = "category")
public class Category {
    @Id
    @SequenceGenerator(name = "pk_seq", sequenceName = "category_table_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk_seq")
    private Integer id;

    @Column(name = "name")
    private String name;

    public Category() {
    }
    // getters and setters ommited
}

UPD2

Now I get this exception:

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is <openjpa-2.3.0-r422266:1540826 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: "
de.alex.web.pag.entity.Category
de.alex.web.pag.entity.Product
de.alex.web.pag.entity.Order".

Solution

  • Your issue here is that by default OpenJPA uses bytecode (compile time) enhancement of persistent entities rather than say, for example, Hibernate's approach of runtime proxies.

    You therefore need to either:

    at compile time enhance the persistent classes. See: http://openjpa.apache.org/entity-enhancement.html. If you are using Maven configure the plugin in your POM. If you are also using Eclipse configure the plugin to save having to run a full 'mvn clean install' on every change to your persistent classes.

    http://openjpa.apache.org/openjpaeclipseenhancementbuilder.html

    or

    enable runtime enhancement: http://openjpa.apache.org/runtime-enhancement.html