Automatically creating and/or extending JPA tables

2019-09-20 08:46发布

问题:

I have experienced a strange matter with a Java EE application running on Wildfly 8.1.0 as the server and Postgres as our database system in combination with EclipseLink as the persistence provider (the reasons why I want to study the costs of migrating from built-in Hibernate to EclipseLink don't matter here).

I was getting used to the Hibernate feature of automatically extending the existing database tables by newly added columns when extending the corresponding Entity classes and it would be charming if EclipseLink was able to do so, too - studying the documentation, EclipseLink provides the property

<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>

which sound good to me, but a short test lead to the disillusioning result that it does not work "out of the box" (see minimal example below). Interestingly, if I simply create the respective table in the database without any columns, the table gets filled and works as I wanted, but neither create-or-extend-tables nor drop-and-create-tables and even not create-tables works - the first two only, if I add the mentioned empty table.

Has anyone encountered a situation like this and possibly found a solution?

Additionally, I learned about a Postgres problem regarding transactions

PostgreSQL seems to abort the transaction if an error occurs, so accessing the database after a failure may not be possible until after calling rollback. (EclipseLink/FAQ/JPA/PostgreSQL)

and as certain error logs point to problems with transactions, maybe this could be a part of the problem?

Minimal Example

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">

    <persistence-unit name="..." transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>java:jboss/datasources/PostgresDS</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
        </properties>
    </persistence-unit>
</persistence>

Name.java

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Name {

    private String id;

    private String name;

    @Id
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

回答1:

You have numerous exceptions in the log, all due to using a JTA datasource and being apart of a transaction. See eclipse.org/forums/index.php/t/440610 for details, but DDL doesn't work inside most transactions, so you will need to trigger EclipseLink to load the persistence unit upfront with the "eclipselink.deploy-on-startup"="true" persistence property.