Skip to content

Commit e0ee9f5

Browse files
gavinkingsebersole
authored andcommitted
make it easy for Hibernate Reactive to reuse the @naturalid stuff
1 parent e368ac5 commit e0ee9f5

File tree

3 files changed

+201
-149
lines changed

3 files changed

+201
-149
lines changed

hibernate-core/src/main/java/org/hibernate/loader/entity/EntityLoader.java

Lines changed: 3 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,15 @@
66
*/
77
package org.hibernate.loader.entity;
88

9-
import org.hibernate.HibernateException;
109
import org.hibernate.LockMode;
1110
import org.hibernate.LockOptions;
1211
import org.hibernate.MappingException;
13-
import org.hibernate.engine.jdbc.Size;
1412
import org.hibernate.engine.spi.LoadQueryInfluencers;
15-
import org.hibernate.engine.spi.Mapping;
1613
import org.hibernate.engine.spi.SessionFactoryImplementor;
1714
import org.hibernate.engine.spi.SharedSessionContractImplementor;
18-
import org.hibernate.internal.util.collections.ArrayHelper;
1915
import org.hibernate.persister.entity.OuterJoinLoadable;
20-
import org.hibernate.type.AbstractType;
2116
import org.hibernate.type.Type;
2217

23-
import java.sql.PreparedStatement;
24-
import java.sql.ResultSet;
25-
import java.sql.SQLException;
26-
import java.util.ArrayList;
27-
import java.util.Arrays;
28-
import java.util.List;
29-
import java.util.Map;
30-
3118
/**
3219
* Loads an entity instance using outerjoin fetching to fetch associated entities.
3320
* <br>
@@ -162,23 +149,14 @@ public EntityLoader(
162149
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
163150
super( persister, new NaturalIdType( persister, valueNullness ), factory, loadQueryInfluencers );
164151

165-
EntityJoinWalker walker = new EntityJoinWalker(
152+
EntityJoinWalker walker = new NaturalIdEntityJoinWalker(
166153
persister,
167-
naturalIdColumns( valueNullness ),
154+
valueNullness,
168155
batchSize,
169156
lockOptions,
170157
factory,
171158
loadQueryInfluencers
172-
) {
173-
@Override
174-
protected StringBuilder whereString(String alias, String[] columnNames, int batchSize) {
175-
StringBuilder sql = super.whereString(alias, columnNames, batchSize);
176-
for (String nullCol : naturalIdColumns( ArrayHelper.negate( valueNullness ) ) ) {
177-
sql.append(" and ").append( getAlias() ).append('.').append(nullCol).append(" is null");
178-
}
179-
return sql;
180-
}
181-
};
159+
);
182160
initFromWalker( walker );
183161
compositeKeyManyToOneTargetIndices = walker.getCompositeKeyManyToOneTargetIndices();
184162
postInstantiate();
@@ -194,17 +172,6 @@ protected StringBuilder whereString(String alias, String[] columnNames, int batc
194172
}
195173
}
196174

197-
private String[] naturalIdColumns(boolean[] valueNullness) {
198-
int i = 0;
199-
List<String> columns = new ArrayList<>();
200-
for ( int p : persister.getNaturalIdentifierProperties() ) {
201-
if ( !valueNullness[i++] ) {
202-
columns.addAll( Arrays.asList( persister.getPropertyColumnNames(p) ) );
203-
}
204-
}
205-
return columns.toArray(ArrayHelper.EMPTY_STRING_ARRAY);
206-
}
207-
208175
public Object loadByUniqueKey(SharedSessionContractImplementor session, Object key) {
209176
return loadByUniqueKey( session, key, null );
210177
}
@@ -223,117 +190,4 @@ public int[][] getCompositeKeyManyToOneTargetIndices() {
223190
return compositeKeyManyToOneTargetIndices;
224191
}
225192

226-
static class NaturalIdType extends AbstractType {
227-
private OuterJoinLoadable persister;
228-
private boolean[] valueNullness;
229-
230-
NaturalIdType(OuterJoinLoadable persister, boolean[] valueNullness) {
231-
this.persister = persister;
232-
this.valueNullness = valueNullness;
233-
}
234-
235-
@Override
236-
public int getColumnSpan(Mapping mapping) throws MappingException {
237-
int span = 0;
238-
int i = 0;
239-
for ( int p : persister.getNaturalIdentifierProperties() ) {
240-
if ( !valueNullness[i++] ) {
241-
span += persister.getPropertyColumnNames(p).length;
242-
}
243-
}
244-
return span;
245-
}
246-
247-
@Override
248-
public int[] sqlTypes(Mapping mapping) throws MappingException {
249-
throw new UnsupportedOperationException();
250-
}
251-
252-
@Override
253-
public Size[] dictatedSizes(Mapping mapping) throws MappingException {
254-
throw new UnsupportedOperationException();
255-
}
256-
257-
@Override
258-
public Size[] defaultSizes(Mapping mapping) throws MappingException {
259-
throw new UnsupportedOperationException();
260-
}
261-
262-
@Override
263-
public Class getReturnedClass() {
264-
throw new UnsupportedOperationException();
265-
}
266-
267-
@Override
268-
public boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SharedSessionContractImplementor session)
269-
throws HibernateException {
270-
throw new UnsupportedOperationException();
271-
}
272-
273-
@Override
274-
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
275-
throws HibernateException, SQLException {
276-
throw new UnsupportedOperationException();
277-
}
278-
279-
@Override
280-
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
281-
throws HibernateException, SQLException {
282-
throw new UnsupportedOperationException();
283-
}
284-
285-
@Override
286-
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
287-
throws HibernateException, SQLException {
288-
throw new UnsupportedOperationException();
289-
}
290-
291-
@Override
292-
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
293-
throws HibernateException, SQLException {
294-
Object[] keys = (Object[]) value;
295-
int i = 0;
296-
for ( int p : persister.getNaturalIdentifierProperties() ) {
297-
if ( !valueNullness[i] ) {
298-
persister.getPropertyTypes()[p].nullSafeSet( st, keys[i], index++, session );
299-
}
300-
i++;
301-
}
302-
}
303-
304-
@Override
305-
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
306-
return "natural id";
307-
}
308-
309-
@Override
310-
public String getName() {
311-
throw new UnsupportedOperationException();
312-
}
313-
314-
@Override
315-
public Object deepCopy(Object value, SessionFactoryImplementor factory) {
316-
throw new UnsupportedOperationException();
317-
}
318-
319-
@Override
320-
public boolean isMutable() {
321-
throw new UnsupportedOperationException();
322-
}
323-
324-
@Override
325-
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) {
326-
throw new UnsupportedOperationException();
327-
}
328-
329-
@Override
330-
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
331-
throw new UnsupportedOperationException();
332-
}
333-
334-
@Override
335-
public boolean[] toColumnNullness(Object value, Mapping mapping) {
336-
throw new UnsupportedOperationException();
337-
}
338-
}
339193
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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.loader.entity;
8+
9+
import org.hibernate.LockOptions;
10+
import org.hibernate.MappingException;
11+
import org.hibernate.engine.spi.LoadQueryInfluencers;
12+
import org.hibernate.engine.spi.SessionFactoryImplementor;
13+
import org.hibernate.persister.entity.Loadable;
14+
import org.hibernate.persister.entity.OuterJoinLoadable;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
19+
import static java.util.Arrays.asList;
20+
import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY;
21+
import static org.hibernate.internal.util.collections.ArrayHelper.negate;
22+
23+
/**
24+
* An {@link EntityJoinWalker} that uses 'is null' predicates to match
25+
* null {@link org.hibernate.annotations.NaturalId} properties.
26+
*
27+
* @author Gavin King
28+
*/
29+
public class NaturalIdEntityJoinWalker extends EntityJoinWalker {
30+
31+
private static String[] naturalIdColumns(Loadable persister, boolean[] valueNullness) {
32+
int i = 0;
33+
List<String> columns = new ArrayList<>();
34+
for ( int p : persister.getNaturalIdentifierProperties() ) {
35+
if ( !valueNullness[i++] ) {
36+
columns.addAll( asList( persister.getPropertyColumnNames(p) ) );
37+
}
38+
}
39+
return columns.toArray(EMPTY_STRING_ARRAY);
40+
}
41+
42+
public NaturalIdEntityJoinWalker(
43+
OuterJoinLoadable persister,
44+
boolean[] valueNullness,
45+
int batchSize,
46+
LockOptions lockOptions,
47+
SessionFactoryImplementor factory,
48+
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
49+
super(persister, naturalIdColumns( persister, valueNullness ), batchSize, lockOptions, factory, loadQueryInfluencers);
50+
StringBuilder sql = new StringBuilder( getSQLString() );
51+
for ( String nullCol : naturalIdColumns( getPersister(), negate( valueNullness ) ) ) {
52+
sql.append(" and ").append( getAlias() ).append('.').append( nullCol ).append(" is null");
53+
}
54+
setSql( sql.toString() );
55+
}
56+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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.loader.entity;
8+
9+
import org.hibernate.HibernateException;
10+
import org.hibernate.MappingException;
11+
import org.hibernate.engine.jdbc.Size;
12+
import org.hibernate.engine.spi.Mapping;
13+
import org.hibernate.engine.spi.SessionFactoryImplementor;
14+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
15+
import org.hibernate.persister.entity.OuterJoinLoadable;
16+
import org.hibernate.type.AbstractType;
17+
18+
import java.sql.PreparedStatement;
19+
import java.sql.ResultSet;
20+
import java.sql.SQLException;
21+
import java.util.Map;
22+
23+
/**
24+
* Workaround for the fact that we don't have a well-defined Hibernate
25+
* type when loading by multiple {@link org.hibernate.annotations.NaturalId}
26+
* properties.
27+
*
28+
* @author Gavin King
29+
*/
30+
public class NaturalIdType extends AbstractType {
31+
private OuterJoinLoadable persister;
32+
private boolean[] valueNullness;
33+
34+
public NaturalIdType(OuterJoinLoadable persister, boolean[] valueNullness) {
35+
this.persister = persister;
36+
this.valueNullness = valueNullness;
37+
}
38+
39+
@Override
40+
public int getColumnSpan(Mapping mapping) throws MappingException {
41+
int span = 0;
42+
int i = 0;
43+
for (int p : persister.getNaturalIdentifierProperties() ) {
44+
if ( !valueNullness[i++] ) {
45+
span += persister.getPropertyColumnNames(p).length;
46+
}
47+
}
48+
return span;
49+
}
50+
51+
@Override
52+
public int[] sqlTypes(Mapping mapping) throws MappingException {
53+
throw new UnsupportedOperationException();
54+
}
55+
56+
@Override
57+
public Size[] dictatedSizes(Mapping mapping) throws MappingException {
58+
throw new UnsupportedOperationException();
59+
}
60+
61+
@Override
62+
public Size[] defaultSizes(Mapping mapping) throws MappingException {
63+
throw new UnsupportedOperationException();
64+
}
65+
66+
@Override
67+
public Class getReturnedClass() {
68+
throw new UnsupportedOperationException();
69+
}
70+
71+
@Override
72+
public boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SharedSessionContractImplementor session)
73+
throws HibernateException {
74+
throw new UnsupportedOperationException();
75+
}
76+
77+
@Override
78+
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
79+
throws HibernateException, SQLException {
80+
throw new UnsupportedOperationException();
81+
}
82+
83+
@Override
84+
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
85+
throws HibernateException, SQLException {
86+
throw new UnsupportedOperationException();
87+
}
88+
89+
@Override
90+
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
91+
throws HibernateException, SQLException {
92+
throw new UnsupportedOperationException();
93+
}
94+
95+
@Override
96+
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
97+
throws HibernateException, SQLException {
98+
Object[] keys = (Object[]) value;
99+
int i = 0;
100+
for ( int p : persister.getNaturalIdentifierProperties() ) {
101+
if ( !valueNullness[i] ) {
102+
persister.getPropertyTypes()[p].nullSafeSet( st, keys[i], index++, session );
103+
}
104+
i++;
105+
}
106+
}
107+
108+
@Override
109+
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
110+
return "natural id";
111+
}
112+
113+
@Override
114+
public String getName() {
115+
throw new UnsupportedOperationException();
116+
}
117+
118+
@Override
119+
public Object deepCopy(Object value, SessionFactoryImplementor factory) {
120+
throw new UnsupportedOperationException();
121+
}
122+
123+
@Override
124+
public boolean isMutable() {
125+
throw new UnsupportedOperationException();
126+
}
127+
128+
@Override
129+
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) {
130+
throw new UnsupportedOperationException();
131+
}
132+
133+
@Override
134+
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
135+
throw new UnsupportedOperationException();
136+
}
137+
138+
@Override
139+
public boolean[] toColumnNullness(Object value, Mapping mapping) {
140+
throw new UnsupportedOperationException();
141+
}
142+
}

0 commit comments

Comments
 (0)