CteInsertStrategy 只能与支持 CTE 且也可以采用 UPDATE 或 DELETE 语句的方言一起使用

hab*_*713 8 java postgresql hibernate jpa common-table-expression

带有 PostgreSQL JDBC 驱动程序 42.3.5 的 Hibernate 6.0.1 会导致以下异常:

java.lang.UnsupportedOperationException:
CteInsertStrategy can only be used with Dialects that support CTE that can take UPDATE or DELETE statements as well
at org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy.<init>(CteInsertStrategy.java:123)
at org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy.<init>(CteInsertStrategy.java:107)
at org.hibernate.dialect.PostgreSQLDialect.getFallbackSqmInsertStrategy(PostgreSQLDialect.java:704)
...
Run Code Online (Sandbox Code Playgroud)

出了什么问题以及如何解决该问题?

MyEntity.java

java.lang.UnsupportedOperationException:
CteInsertStrategy can only be used with Dialects that support CTE that can take UPDATE or DELETE statements as well
at org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy.<init>(CteInsertStrategy.java:123)
at org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy.<init>(CteInsertStrategy.java:107)
at org.hibernate.dialect.PostgreSQLDialect.getFallbackSqmInsertStrategy(PostgreSQLDialect.java:704)
...
Run Code Online (Sandbox Code Playgroud)

MyTest.java

import jakarta.persistence.*;

@Entity
@Table(name = "my_entity")
public class MyEntity {

    private Long id;

    @Id
    @SequenceGenerator(name = "id_sequence", sequenceName = "my_id_sequence")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence")
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }

}
Run Code Online (Sandbox Code Playgroud)

休眠配置文件

import static org.junit.Assert.assertNotNull;

import org.hibernate.*;
import org.hibernate.cfg.*;
import org.junit.*;

public class MyTest {

    private static Configuration configuration;
    private static SessionFactory sessionFactory;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        sessionFactory.close();
    }

    private Session session;

    @Before
    public void setUp() throws Exception {
        session = sessionFactory.openSession();
    }

    @After
    public void tearDown() throws Exception {
        session.close();
    }

    @Test
    public void test() {
        Transaction transaction = session.beginTransaction();
        MyEntity entity = new MyEntity();
        session.persist(entity);
        assertNotNull(entity.getId());
        transaction.commit();
    }

}
Run Code Online (Sandbox Code Playgroud)

构建.gradle

plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

ext {
    hibernateVersion = '6.0.1.Final'
}

dependencies {
    implementation 'org.postgresql:postgresql:42.3.5'
    implementation 'org.hibernate.orm:hibernate-c3p0:' + hibernateVersion
    implementation 'org.hibernate.orm:hibernate-core:' + hibernateVersion
    testImplementation 'junit:junit:4.13.2'
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处的完整源代码。

hab*_*713 7

配置属性use_jdbc_metadata_defaults必须用于trueHibernate 检测 PostgreSQL 方言的正确版本。

删除这一行

<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
Run Code Online (Sandbox Code Playgroud)

hibernate.cfg.xml解决问题。

(感谢Hibernate Zulip 频道的 Christian解决了这个问题。)

  • 就我而言,原因更简单且不太明显:连接用户的密码错误 (3认同)