Skip to content

Commit a0f0ca4

Browse files
committed
[#255] Overrides default IdentityGenerator
1 parent 120aa35 commit a0f0ca4

File tree

5 files changed

+216
-15
lines changed

5 files changed

+216
-15
lines changed

hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractEntityPersister.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.hibernate.jdbc.Expectation;
4343
import org.hibernate.loader.entity.UniqueEntityLoader;
4444
import org.hibernate.persister.entity.AbstractEntityPersister;
45-
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
4645
import org.hibernate.persister.entity.Lockable;
4746
import org.hibernate.persister.entity.MultiLoadOptions;
4847
import org.hibernate.persister.entity.OuterJoinLoadable;
@@ -74,7 +73,6 @@
7473
import static org.hibernate.pretty.MessageHelper.infoString;
7574
import static org.hibernate.reactive.adaptor.impl.PreparedStatementAdaptor.bind;
7675
import static org.hibernate.reactive.id.impl.IdentifierGeneration.castToIdentifierType;
77-
import static org.hibernate.reactive.persister.entity.impl.InsertAndSelectProcessor.process;
7876
import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture;
7977
import static org.hibernate.reactive.util.impl.CompletionStages.logSqlException;
8078
import static org.hibernate.reactive.util.impl.CompletionStages.loop;
@@ -100,7 +98,7 @@
10098
* @see ReactiveSingleTableEntityPersister
10199
*/
102100
public interface ReactiveAbstractEntityPersister extends ReactiveEntityPersister, OuterJoinLoadable, Lockable {
103-
Logger log = Logger.getLogger( JoinedSubclassEntityPersister.class );
101+
Logger log = Logger.getLogger( ReactiveAbstractEntityPersister.class );
104102

105103
default Parameters parameters() {
106104
return Parameters.instance( getFactory().getJdbcServices().getDialect() );
@@ -368,10 +366,7 @@ default CompletionStage<Serializable> insertReactive(
368366
// Ignoring it for now because it's always false and we have ways to get the id without
369367
// the extra round trip for all supported databases
370368
// if ( getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled() ) {
371-
generatedIdStage = connection.insertAndSelectIdentifier(
372-
process( sql, getFactory().getJdbcServices().getDialect(), delegate().getIdentifierColumnNames()[0] ),
373-
params
374-
);
369+
generatedIdStage = connection.insertAndSelectIdentifier( sql, params );
375370
// }
376371
// else {
377372
// //use an extra round trip to fetch the id
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.persister.entity.impl;
7+
8+
import java.util.Iterator;
9+
10+
import org.hibernate.HibernateException;
11+
import org.hibernate.MappingException;
12+
import org.hibernate.dialect.CockroachDB192Dialect;
13+
import org.hibernate.dialect.DB2Dialect;
14+
import org.hibernate.dialect.Dialect;
15+
import org.hibernate.dialect.PostgreSQL81Dialect;
16+
import org.hibernate.dialect.SQLServerDialect;
17+
import org.hibernate.id.IdentityGenerator;
18+
import org.hibernate.id.PostInsertIdentityPersister;
19+
import org.hibernate.id.insert.IdentifierGeneratingInsert;
20+
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
21+
import org.hibernate.sql.Insert;
22+
23+
/**
24+
* Fix the insert and select id queries generated by Hibernate ORM
25+
*/
26+
public class ReactiveIdentityGenerator extends IdentityGenerator {
27+
28+
@Override
29+
public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
30+
PostInsertIdentityPersister persister, Dialect dialect, boolean isGetGeneratedKeysEnabled)
31+
throws HibernateException {
32+
return new ReactiveInsertAndSelectDelegate( persister, dialect );
33+
}
34+
35+
public static class ReactiveInsertAndSelectDelegate extends InsertSelectDelegate {
36+
37+
private final PostInsertIdentityPersister persister;
38+
private final Dialect dialect;
39+
40+
public ReactiveInsertAndSelectDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
41+
super( persister, dialect );
42+
this.persister = persister;
43+
this.dialect = dialect;
44+
}
45+
46+
@Override
47+
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
48+
IdentifierGeneratingInsert insert = createInsert();
49+
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] );
50+
return insert;
51+
}
52+
53+
private IdentifierGeneratingInsert createInsert() {
54+
if ( dialect instanceof PostgreSQL81Dialect || dialect instanceof CockroachDB192Dialect ) {
55+
return new PostgresIdentifierGeneratingInsert( dialect );
56+
}
57+
if ( dialect instanceof SQLServerDialect ) {
58+
return new SqlServerIdentifierGeneratingInsert( dialect );
59+
}
60+
if ( dialect instanceof DB2Dialect ) {
61+
return new Db2IdentifierGeneratingInsert( dialect );
62+
}
63+
return super.prepareIdentifierGeneratingInsert();
64+
}
65+
}
66+
67+
public static class Db2IdentifierGeneratingInsert extends IdentifierGeneratingInsert {
68+
69+
private String identityColumnName;
70+
71+
public Db2IdentifierGeneratingInsert(Dialect dialect) {
72+
super( dialect );
73+
}
74+
75+
@Override
76+
public Insert addIdentityColumn(String columnName) {
77+
this.identityColumnName = columnName;
78+
return super.addIdentityColumn( columnName );
79+
}
80+
81+
/**
82+
* @see Insert#toStatementString()
83+
*/
84+
@Override
85+
public String toStatementString() {
86+
return "select " + identityColumnName + " from NEW TABLE (" + super.toStatementString() + ")";
87+
}
88+
}
89+
90+
public static class PostgresIdentifierGeneratingInsert extends IdentifierGeneratingInsert {
91+
92+
private String identityColumnName;
93+
94+
public PostgresIdentifierGeneratingInsert(Dialect dialect) {
95+
super( dialect );
96+
}
97+
98+
@Override
99+
public Insert addIdentityColumn(String columnName) {
100+
this.identityColumnName = columnName;
101+
return super.addIdentityColumn( columnName );
102+
}
103+
104+
@Override
105+
public String toStatementString() {
106+
return super.toStatementString() + " returning " + identityColumnName;
107+
}
108+
}
109+
110+
public static class SqlServerIdentifierGeneratingInsert extends IdentifierGeneratingInsert {
111+
private String identityColumnName;
112+
113+
public SqlServerIdentifierGeneratingInsert(Dialect dialect) {
114+
super( dialect );
115+
}
116+
117+
@Override
118+
public Insert addIdentityColumn(String columnName) {
119+
this.identityColumnName = columnName;
120+
return super.addIdentityColumn( columnName );
121+
}
122+
123+
/**
124+
* @see Insert#toStatementString()
125+
*/
126+
public String toStatementString() {
127+
StringBuilder buf = new StringBuilder( columns.size() * 15 + tableName.length() + 10 );
128+
if ( comment != null ) {
129+
buf.append( "/* " ).append( Dialect.escapeComment( comment ) ).append( " */ " );
130+
}
131+
buf.append( "insert into " ).append( tableName );
132+
if ( columns.size() == 0 ) {
133+
if ( getDialect().supportsNoColumnsInsert() ) {
134+
// This line is missing in ORM
135+
buf.append( " output inserted." ).append( identityColumnName );
136+
buf.append( ' ' ).append( getDialect().getNoColumnsInsertString() );
137+
}
138+
else {
139+
throw new MappingException( String.format(
140+
"The INSERT statement for table [%s] contains no column, and this is not supported by [%s]",
141+
tableName,
142+
getDialect()
143+
)
144+
);
145+
}
146+
}
147+
else {
148+
buf.append( " (" );
149+
Iterator<String> iter = columns.keySet().iterator();
150+
while ( iter.hasNext() ) {
151+
buf.append( iter.next() );
152+
if ( iter.hasNext() ) {
153+
buf.append( ", " );
154+
}
155+
}
156+
buf.append( ")");
157+
// This line is missing in ORM
158+
buf.append( " output inserted." ).append( identityColumnName );
159+
buf.append( " values (" );
160+
iter = columns.values().iterator();
161+
while ( iter.hasNext() ) {
162+
buf.append( iter.next() );
163+
if ( iter.hasNext() ) {
164+
buf.append( ", " );
165+
}
166+
}
167+
buf.append( ')' );
168+
}
169+
return buf.toString();
170+
}
171+
}
172+
173+
}

hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveJoinedSubclassEntityPersister.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
*/
66
package org.hibernate.reactive.persister.entity.impl;
77

8+
import java.io.Serializable;
9+
import java.sql.PreparedStatement;
10+
import java.util.concurrent.CompletionStage;
11+
812
import org.hibernate.HibernateException;
913
import org.hibernate.LockMode;
1014
import org.hibernate.LockOptions;
@@ -15,6 +19,8 @@
1519
import org.hibernate.engine.spi.EntityEntry;
1620
import org.hibernate.engine.spi.LoadQueryInfluencers;
1721
import org.hibernate.engine.spi.SharedSessionContractImplementor;
22+
import org.hibernate.id.IdentifierGenerator;
23+
import org.hibernate.id.IdentityGenerator;
1824
import org.hibernate.jdbc.Expectation;
1925
import org.hibernate.loader.entity.UniqueEntityLoader;
2026
import org.hibernate.mapping.PersistentClass;
@@ -25,10 +31,6 @@
2531
import org.hibernate.reactive.loader.entity.impl.ReactiveCascadeEntityLoader;
2632
import org.hibernate.type.Type;
2733

28-
import java.io.Serializable;
29-
import java.sql.PreparedStatement;
30-
import java.util.concurrent.CompletionStage;
31-
3234
/**
3335
* An {@link ReactiveEntityPersister} backed by {@link JoinedSubclassEntityPersister}
3436
* and {@link ReactiveAbstractEntityPersister}.
@@ -115,6 +117,15 @@ public String generateIdentityInsertString(boolean[] includeProperty) {
115117
return parameters().process( sql, includeProperty.length );
116118
}
117119

120+
@Override
121+
public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
122+
final IdentifierGenerator identifierGenerator = super.getIdentifierGenerator();
123+
if ( identifierGenerator instanceof IdentityGenerator ) {
124+
return new ReactiveIdentityGenerator();
125+
}
126+
return identifierGenerator;
127+
}
128+
118129
@Override
119130
public boolean hasProxy() {
120131
return hasUnenhancedProxy();

hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveSingleTableEntityPersister.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.hibernate.engine.spi.EntityEntry;
2222
import org.hibernate.engine.spi.LoadQueryInfluencers;
2323
import org.hibernate.engine.spi.SharedSessionContractImplementor;
24+
import org.hibernate.id.IdentifierGenerator;
25+
import org.hibernate.id.IdentityGenerator;
2426
import org.hibernate.jdbc.Expectation;
2527
import org.hibernate.loader.entity.UniqueEntityLoader;
2628
import org.hibernate.mapping.PersistentClass;
@@ -127,6 +129,15 @@ public String generateIdentityInsertString(boolean[] includeProperty) {
127129
return parameters().process( sql, includeProperty.length );
128130
}
129131

132+
@Override
133+
public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
134+
final IdentifierGenerator identifierGenerator = super.getIdentifierGenerator();
135+
if ( identifierGenerator instanceof IdentityGenerator ) {
136+
return new ReactiveIdentityGenerator();
137+
}
138+
return identifierGenerator;
139+
}
140+
130141
@Override
131142
public boolean hasProxy() {
132143
return hasUnenhancedProxy();

hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveUnionSubclassEntityPersister.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
*/
66
package org.hibernate.reactive.persister.entity.impl;
77

8+
import java.io.Serializable;
9+
import java.sql.PreparedStatement;
10+
import java.util.concurrent.CompletionStage;
11+
812
import org.hibernate.HibernateException;
913
import org.hibernate.LockMode;
1014
import org.hibernate.LockOptions;
@@ -15,6 +19,8 @@
1519
import org.hibernate.engine.spi.EntityEntry;
1620
import org.hibernate.engine.spi.LoadQueryInfluencers;
1721
import org.hibernate.engine.spi.SharedSessionContractImplementor;
22+
import org.hibernate.id.IdentifierGenerator;
23+
import org.hibernate.id.IdentityGenerator;
1824
import org.hibernate.jdbc.Expectation;
1925
import org.hibernate.loader.entity.UniqueEntityLoader;
2026
import org.hibernate.mapping.PersistentClass;
@@ -25,10 +31,6 @@
2531
import org.hibernate.reactive.loader.entity.impl.ReactiveCascadeEntityLoader;
2632
import org.hibernate.type.Type;
2733

28-
import java.io.Serializable;
29-
import java.sql.PreparedStatement;
30-
import java.util.concurrent.CompletionStage;
31-
3234
/**
3335
* An {@link ReactiveEntityPersister} backed by {@link UnionSubclassEntityPersister}
3436
* and {@link ReactiveAbstractEntityPersister}.
@@ -114,6 +116,15 @@ public String generateIdentityInsertString(boolean[] includeProperty) {
114116
return parameters().process( sql, includeProperty.length );
115117
}
116118

119+
@Override
120+
public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
121+
final IdentifierGenerator identifierGenerator = super.getIdentifierGenerator();
122+
if ( identifierGenerator instanceof IdentityGenerator ) {
123+
return new ReactiveIdentityGenerator();
124+
}
125+
return identifierGenerator;
126+
}
127+
117128
@Override
118129
public boolean hasProxy() {
119130
return hasUnenhancedProxy();

0 commit comments

Comments
 (0)