HHH-13202 - Add support for PostgreSQL "GENERATED BY DEFAULT AS IDENTITY"
HHH-13106 - Hibernate fails with Schema-validation: missing sequence
This commit is contained in:
parent
ba4d742d34
commit
76981d97a8
|
@ -38,7 +38,7 @@ ext {
|
|||
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
|
||||
],
|
||||
pgsql_docker : [
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQL95Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQL10Dialect',
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
|
|
|
@ -403,7 +403,7 @@ public enum Database {
|
|||
POSTGRESQL {
|
||||
@Override
|
||||
public Class<? extends Dialect> latestDialect() {
|
||||
return PostgreSQL95Dialect.class;
|
||||
return PostgreSQL10Dialect.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -432,7 +432,7 @@ public enum Database {
|
|||
else if ( minorVersion < 5 ) {
|
||||
return new PostgreSQL94Dialect();
|
||||
}
|
||||
else if ( minorVersion < 6 ) {
|
||||
else {
|
||||
return new PostgreSQL95Dialect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||
import org.hibernate.dialect.identity.PostgreSQL10IdentityColumnSupport;
|
||||
|
||||
/**
|
||||
* An SQL dialect for Postgres 10 and later.
|
||||
*/
|
||||
public class PostgreSQL10Dialect extends PostgreSQL95Dialect {
|
||||
|
||||
@Override
|
||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
return new PostgreSQL10IdentityColumnSupport();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect.identity;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class PostgreSQL10IdentityColumnSupport extends IdentityColumnSupportImpl {
|
||||
@Override
|
||||
public boolean supportsIdentityColumns() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentitySelectString(String table, String column, int type) {
|
||||
return "select currval('" + table + '_' + column + "_seq')";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentityColumnString(int type) {
|
||||
return "generated by default as identity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDataTypeInIdentityColumn() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -129,7 +129,8 @@ public class DialectFactoryTest extends BaseUnitTestCase {
|
|||
testDetermination( "PostgreSQL", 9, 3, PostgreSQL92Dialect.class, resolver );
|
||||
testDetermination( "PostgreSQL", 9, 4, PostgreSQL94Dialect.class, resolver );
|
||||
testDetermination( "PostgreSQL", 9, 5, PostgreSQL95Dialect.class, resolver );
|
||||
testDetermination( "PostgreSQL", 10, 0, PostgreSQL95Dialect.class, resolver );
|
||||
testDetermination( "PostgreSQL", 9, 6, PostgreSQL95Dialect.class, resolver );
|
||||
testDetermination( "PostgreSQL", 10, 0, PostgreSQL10Dialect.class, resolver );
|
||||
testDetermination( "EnterpriseDB", 9, 2, PostgresPlusDialect.class, resolver );
|
||||
testDetermination( "Apache Derby", 10, 4, DerbyDialect.class, resolver );
|
||||
testDetermination( "Apache Derby", 10, 5, DerbyTenFiveDialect.class, resolver );
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.sequence;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.PostgreSQL10Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Vlad Mhalcea
|
||||
*/
|
||||
@RequiresDialect(jiraKey = "HHH-13106", value = PostgreSQL10Dialect.class)
|
||||
public class PostgreSQLIdentitySequenceTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] { Role.class };
|
||||
}
|
||||
|
||||
private DriverManagerConnectionProviderImpl connectionProvider;
|
||||
|
||||
@Override
|
||||
public void buildEntityManagerFactory() {
|
||||
connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
connectionProvider.configure( Environment.getProperties() );
|
||||
|
||||
try(Connection connection = connectionProvider.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute( "DROP TABLE IF EXISTS roles CASCADE" );
|
||||
statement.execute( "CREATE TABLE roles ( id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY )" );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
super.buildEntityManagerFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseResources() {
|
||||
super.releaseResources();
|
||||
|
||||
try(Connection connection = connectionProvider.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute( "DROP TABLE IF EXISTS roles CASCADE" );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
if ( connectionProvider != null ) {
|
||||
connectionProvider.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Role role = new Role();
|
||||
entityManager.persist( role );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Role")
|
||||
public static class Role {
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@SequenceGenerator(name = "roles_id_seq", sequenceName = "roles_id_seq", allocationSize = 1)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "roles_id_seq")
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.id.sequence;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.dialect.PostgreSQL10Dialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Vlad Mhalcea
|
||||
*/
|
||||
@RequiresDialect(jiraKey = "HHH-13202", value = PostgreSQL10Dialect.class)
|
||||
public class PostgreSQLIdentitySupportTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] { Role.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Role _role = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Role role = new Role();
|
||||
|
||||
entityManager.persist( role );
|
||||
|
||||
return role;
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Role role = entityManager.find( Role.class, _role.getId() );
|
||||
assertNotNull(role);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Role")
|
||||
public static class Role {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue