Skip to content

Commit a2555cf

Browse files
committed
HHH-15561 - Fixed and added test for issue
Signed-off-by: Jan Schatteman <[email protected]>
1 parent 0b3dd79 commit a2555cf

File tree

7 files changed

+186
-3
lines changed

7 files changed

+186
-3
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.hibernate.dialect.function.StandardSQLFunction;
2121
import org.hibernate.dialect.function.VarArgsSQLFunction;
2222
import org.hibernate.dialect.hint.IndexQueryHintHandler;
23+
import org.hibernate.dialect.identity.H2FinalTableIdentityColumnSupport;
2324
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
2425
import org.hibernate.dialect.identity.IdentityColumnSupport;
2526
import org.hibernate.dialect.pagination.AbstractLimitHandler;
@@ -505,7 +506,7 @@ public boolean supportsIfExistsBeforeTableName() {
505506

506507
@Override
507508
public IdentityColumnSupport getIdentityColumnSupport() {
508-
return new H2IdentityColumnSupport();
509+
return isVersion2 ? H2FinalTableIdentityColumnSupport.INSTANCE : H2IdentityColumnSupport.INSTANCE;
509510
}
510511

511512
@Override
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.dialect.identity;
8+
9+
/**
10+
* Identity column support for H2 2+ versions
11+
* @author Jan Schatteman
12+
*/
13+
public class H2FinalTableIdentityColumnSupport extends H2IdentityColumnSupport {
14+
15+
public static final H2FinalTableIdentityColumnSupport INSTANCE = new H2FinalTableIdentityColumnSupport();
16+
17+
private H2FinalTableIdentityColumnSupport() {
18+
}
19+
20+
@Override
21+
public boolean supportsInsertSelectIdentity() {
22+
return true;
23+
}
24+
25+
@Override
26+
public String appendIdentitySelectToInsert(String identityColumnName, String insertString) {
27+
return "select " + identityColumnName + " from final table ( " + insertString + " )";
28+
}
29+
}

hibernate-core/src/main/java/org/hibernate/dialect/identity/H2IdentityColumnSupport.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
* @author Andrea Boriero
1111
*/
1212
public class H2IdentityColumnSupport extends IdentityColumnSupportImpl {
13+
14+
public static final H2IdentityColumnSupport INSTANCE = new H2IdentityColumnSupport();
15+
16+
protected H2IdentityColumnSupport() {
17+
}
18+
1319
@Override
1420
public boolean supportsIdentityColumns() {
1521
return true;

hibernate-core/src/main/java/org/hibernate/dialect/identity/IdentityColumnSupport.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ public interface IdentityColumnSupport {
5656
*/
5757
String appendIdentitySelectToInsert(String insertString);
5858

59+
/**
60+
* Provided we {@link #supportsInsertSelectIdentity}, then attach the
61+
* "select identity" clause to the insert statement.
62+
* <p/>
63+
* Note, if {@link #supportsInsertSelectIdentity} == false then
64+
* the insert-string should be returned without modification.
65+
*
66+
* @param identityColumnName The name of the identity column
67+
* @param insertString The insert command
68+
*
69+
* @return The insert command with any necessary identity select
70+
* clause attached.
71+
*/
72+
default String appendIdentitySelectToInsert(String identityColumnName, String insertString) {
73+
return appendIdentitySelectToInsert( insertString );
74+
}
75+
5976
/**
6077
* Get the select command to use to retrieve the last generated IDENTITY
6178
* value for a particular table

hibernate-core/src/main/java/org/hibernate/id/insert/InsertSelectIdentityInsert.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.id.insert;
88
import org.hibernate.dialect.Dialect;
9+
import org.hibernate.sql.Insert;
910

1011
/**
1112
* Specialized IdentifierGeneratingInsert which appends the database
@@ -15,11 +16,18 @@
1516
* @author Steve Ebersole
1617
*/
1718
public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
19+
protected String identityColumnName;
20+
21+
public Insert addIdentityColumn(String columnName) {
22+
identityColumnName = columnName;
23+
return super.addIdentityColumn( columnName );
24+
}
25+
1826
public InsertSelectIdentityInsert(Dialect dialect) {
1927
super( dialect );
2028
}
2129

2230
public String toStatementString() {
23-
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( super.toStatementString() );
31+
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( identityColumnName, super.toStatementString() );
2432
}
2533
}

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2941,7 +2941,7 @@ else if ( includeProperty[i] ) {
29412941

29422942
// append the SQL to return the generated identifier
29432943
if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert
2944-
result = getFactory().getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( result );
2944+
result = getFactory().getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( getKeyColumns( 0 )[0], result );
29452945
}
29462946

29472947
return result;
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.id;
8+
9+
import java.util.Date;
10+
import javax.persistence.Entity;
11+
import javax.persistence.GeneratedValue;
12+
import javax.persistence.GenerationType;
13+
import javax.persistence.Id;
14+
15+
import org.hibernate.SessionFactory;
16+
import org.hibernate.boot.Metadata;
17+
import org.hibernate.boot.MetadataSources;
18+
import org.hibernate.boot.registry.StandardServiceRegistry;
19+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
20+
import org.hibernate.cfg.AvailableSettings;
21+
import org.hibernate.dialect.H2Dialect;
22+
import org.hibernate.testing.RequiresDialect;
23+
import org.hibernate.testing.TestForIssue;
24+
import org.hibernate.testing.junit4.BaseUnitTestCase;
25+
26+
import org.junit.Test;
27+
28+
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
29+
import static org.junit.Assert.fail;
30+
31+
32+
/**
33+
* @author Jan Schatteman
34+
*/
35+
@TestForIssue(jiraKey = "HHH-15561")
36+
@RequiresDialect( value = { H2Dialect.class } )
37+
public class IdentityIdEntityTest extends BaseUnitTestCase {
38+
39+
@Test
40+
public void testIdentityEntityWithDisabledGetGeneratedKeys() {
41+
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
42+
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
43+
.applySetting( AvailableSettings.USE_GET_GENERATED_KEYS, "false" )
44+
.build();
45+
46+
Metadata metadata = new MetadataSources( serviceRegistry )
47+
.addAnnotatedClass( IdentityEntity.class )
48+
.buildMetadata();
49+
50+
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
51+
.build();
52+
53+
doInHibernate(
54+
() -> sessionFactory,
55+
session -> {
56+
try {
57+
IdentityEntity ie = new IdentityEntity();
58+
ie.setTimestamp( new Date() );
59+
session.persist( ie );
60+
}
61+
catch (Exception e) {
62+
fail( "Creation of an IDENTITY-id-based entity failed when \"hibernate.jdbc.use_get_generated_keys\" was set to false (" + e.getMessage() + ")" );
63+
}
64+
}
65+
);
66+
}
67+
68+
@Test
69+
public void testIdentityEntityWithDisabledJdbcMetadataDefaults() {
70+
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
71+
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
72+
.applySetting( "use_jdbc_metadata_defaults", "false" )
73+
.build();
74+
75+
Metadata metadata = new MetadataSources( serviceRegistry )
76+
.addAnnotatedClass( IdentityEntity.class )
77+
.buildMetadata();
78+
79+
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
80+
.build();
81+
82+
doInHibernate(
83+
() -> sessionFactory,
84+
session -> {
85+
try {
86+
IdentityEntity ie = new IdentityEntity();
87+
ie.setTimestamp( new Date() );
88+
session.persist( ie );
89+
}
90+
catch (Exception e) {
91+
fail( "Creation of an IDENTITY-id-based entity failed when \"use_jdbc_metadata_defaults\" was set to false (" + e.getMessage() + ")" );
92+
}
93+
}
94+
);
95+
}
96+
97+
@Entity(name = "id_entity")
98+
public static class IdentityEntity {
99+
@Id
100+
@GeneratedValue(strategy = GenerationType.IDENTITY)
101+
private int id;
102+
103+
private Date timestamp;
104+
105+
public int getId() {
106+
return id;
107+
}
108+
109+
public void setId(int id) {
110+
this.id = id;
111+
}
112+
113+
public Date getTimestamp() {
114+
return timestamp;
115+
}
116+
117+
public void setTimestamp(Date timestamp) {
118+
this.timestamp = timestamp;
119+
}
120+
}
121+
122+
}

0 commit comments

Comments
 (0)