具有 PostgreSQL 初始序列池和更改的 JPA 2

JPA 2 with PostgreSQL initial sequence pooling and alteration

我有 Java SE 应用程序使用 Eclipselink 作为 Postgres 数据库的持久性提供程序,我在应用程序初始化时遇到了奇怪的行为。 事情是我的一个实体将 ID 设置为从 postgres 的序列中汇集。在应用程序初始化时,将日志记录级别设置为正常,我可以看到该 ID 被提取了两次,因此序列每次都递增 1。 日志:

 [EL Info]: 2015-01-22 19:25:13.659--ServerSession(1107730949)--Thread(Thread[main,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Fine]: connection: 2015-01-22 19:25:13.751--Thread(Thread[main,5,main])--Detected database platform: org.eclipse.persistence.platform.database.PostgreSQLPlatform
[EL Config]: connection: 2015-01-22 19:25:13.766--ServerSession(1107730949)--Connection(1370979551)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
    platform=>PostgreSQLPlatform
    user name=> "intime"
    datasource URL=> "jdbc:postgresql://localhost:5432/InTime?charSet=LATIN2"
))
[EL Config]: connection: 2015-01-22 19:25:13.77--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--Connected: jdbc:postgresql://localhost:5432/InTime?charSet=LATIN2
    User: intime
    Database: PostgreSQL  Version: 9.3.5
    Driver: PostgreSQL Native Driver  Version: PostgreSQL 9.3 JDBC4.1 (build 1102)
[EL Info]: connection: 2015-01-22 19:25:13.901--ServerSession(1107730949)--Thread(Thread[main,5,main])--file:/home/tepo/IdeaProjects/WebParser/target/classes/_parser_writable login successful
[EL Fine]: sql: 2015-01-22 19:25:13.986--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--select nextval(timetable)
[EL Fine]: sql: 2015-01-22 19:25:13.99--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--ALTER SEQUENCE timetable INCREMENT BY 1
[EL Fine]: sql: 2015-01-22 19:25:13.992--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--select nextval(timetable)
[EL Fine]: sql: 2015-01-22 19:25:13.993--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--ALTER SEQUENCE timetable INCREMENT BY 1
[EL Fine]: sql: 2015-01-22 19:25:14.041--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--SELECT ID, CODE, DAYCAT FROM "public"."DAYCATCODEMAP"
[EL Fine]: sql: 2015-01-22 19:25:14.049--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--SELECT ID, CODE, READABLE FROM "public"."CT_EXCLUSION"
[EL Fine]: sql: 2015-01-22 19:25:14.05--ServerSession(1107730949)--Connection(1142931081)--Thread(Thread[main,5,main])--SELECT ID, ABBREVIATION, FULLNAME FROM "public"."REGION"

这发生在应用初始化的最开始,甚至在 entityManagerFactory 初始化之前。

最后,当应用程序为 运行 时,这会导致插入带有移位 ID 的记录。 这是一个实体:

@Table(name = "\"TIMETABLE\"", catalog = "public")
@Entity
@NamedQuery(
        name = "deleteTimetableByIds",
        query = "DELETE FROM Timetable T where T.id = :id"
)
@SequenceGenerator(name="TTBL_SEQ", sequenceName="timetable", allocationSize = 1)
public class Timetable{

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TTBL_SEQ")
    private Long id;
...
}

persistence.xml:

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

    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>

    <properties>
        <property name="javax.persistence.target-database" value="PostgreSQL" />
        <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
        <property name="javax.persistence.jdbc.url"
                  value="jdbc:postgresql://localhost:5432/InTime?charSet=LATIN2"/>
        <property name="javax.persistence.jdbc.user" value="intime"/>
        <property name="javax.persistence.jdbc.password" value="intime"/>

        <!-- EclipseLink should create the database schema automatically -->
        <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
        <property name="eclipselink.ddl-generation.output-mode"
                  value="database"/>
        <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
</persistence-unit>

所以,当我初始化 PersistenceManager class 时会发生这种情况,这意味着此方法:

private static EntityManager em_write = null;
    private static EntityManagerFactory factory;

    public static void initializeEntityManager() {
        if (em_write == null) {
            factory = Persistence.createEntityManagerFactory("parser_writable");
            em_write = factory.createEntityManager();
        }

明显的问题是为什么会发生这种情况以及如何避免这种情况?

我认为问题是:您在 class 之上使用 @SequenceGenerator 尝试使用 @SequenceGenerator@GeneratedValue 注释仅适用于 pk/unique 列:

@Id
@SequenceGenerator(name="TTBL_SEQ", sequenceName="timetable", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TTBL_SEQ")
private Long id;

知道了!

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

造成了这个麻烦。也许我应该提出错误报告..