Project

General

Profile

« Previous | Next » 

Revision aefcbf9a

Added by Cherian Mathew almost 9 years ago

added class to override Hibernate EntityType class to fix problem with merge replace

View differences:

.gitattributes
1537 1537
cdmlib-persistence/src/main/java/org/hibernate/dialect/MySQL5InnoDBUtf8Dialect.java -text
1538 1538
cdmlib-persistence/src/main/java/org/hibernate/dialect/MySQL5MyISAMUtf8Dialect.java -text
1539 1539
cdmlib-persistence/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java -text
1540
cdmlib-persistence/src/main/java/org/hibernate/type/EntityType.java -text
1540 1541
cdmlib-persistence/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator -text
1541 1542
cdmlib-persistence/src/main/resources/c3p0-config.xml -text
1542 1543
cdmlib-persistence/src/main/resources/eu/etaxonomy/cdm/cdm.datasources.xml -text
cdmlib-persistence/src/main/java/org/hibernate/type/EntityType.java
1
/*
2
 * Hibernate, Relational Persistence for Idiomatic Java
3
 *
4
 * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
5
 * indicated by the @author tags or express copyright attribution
6
 * statements applied by the authors.  All third-party contributions are
7
 * distributed under license by Red Hat Inc.
8
 *
9
 * This copyrighted material is made available to anyone wishing to use, modify,
10
 * copy, or redistribute it subject to the terms and conditions of the GNU
11
 * Lesser General Public License, as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
16
 * for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this distribution; if not, write to:
20
 * Free Software Foundation, Inc.
21
 * 51 Franklin Street, Fifth Floor
22
 * Boston, MA  02110-1301  USA
23
 */
24
package org.hibernate.type;
25

  
26
import java.io.Serializable;
27
import java.sql.ResultSet;
28
import java.sql.SQLException;
29
import java.util.Map;
30

  
31
import org.dom4j.Element;
32
import org.dom4j.Node;
33
import org.hibernate.AssertionFailure;
34
import org.hibernate.EntityMode;
35
import org.hibernate.HibernateException;
36
import org.hibernate.MappingException;
37
import org.hibernate.engine.internal.ForeignKeys;
38
import org.hibernate.engine.spi.EntityUniqueKey;
39
import org.hibernate.engine.spi.Mapping;
40
import org.hibernate.engine.spi.PersistenceContext;
41
import org.hibernate.engine.spi.SessionFactoryImplementor;
42
import org.hibernate.engine.spi.SessionImplementor;
43
import org.hibernate.internal.util.ReflectHelper;
44
import org.hibernate.persister.entity.EntityPersister;
45
import org.hibernate.persister.entity.Joinable;
46
import org.hibernate.persister.entity.UniqueKeyLoadable;
47
import org.hibernate.proxy.HibernateProxy;
48
import org.hibernate.tuple.ElementWrapper;
49

  
50
/**
51
 * Base for types which map associations to persistent entities.
52
 *
53
 * Note : This class overrides the Hibernate EntityType class to provide a
54
 * workaround for problem in method 'replace'. Need to check if
55
 * this problem is fixed in later versions of hibernate or open a bug report
56
 * with a patch.
57
 *
58
 * @author Gavin King
59
 */
60
public abstract class EntityType extends AbstractType implements AssociationType {
61

  
62
	private final TypeFactory.TypeScope scope;
63
	private final String associatedEntityName;
64
	protected final String uniqueKeyPropertyName;
65
	protected final boolean isEmbeddedInXML;
66
	private final boolean eager;
67
	private final boolean unwrapProxy;
68

  
69
	private transient Class returnedClass;
70

  
71
	/**
72
	 * Constructs the requested entity type mapping.
73
	 *
74
	 * @param scope The type scope
75
	 * @param entityName The name of the associated entity.
76
	 * @param uniqueKeyPropertyName The property-ref name, or null if we
77
	 * reference the PK of the associated entity.
78
	 * @param eager Is eager fetching enabled.
79
	 * @param isEmbeddedInXML Should values of this mapping be embedded in XML modes?
80
	 * @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
81
	 * says to return the "implementation target" of lazy prooxies; typically only possible
82
	 * with lazy="no-proxy".
83
	 *
84
	 * @deprecated Use {@link #EntityType(TypeFactory.TypeScope, String, String, boolean, boolean )} instead.
85
	 * See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
86
	 */
87
	@Deprecated
88
	protected EntityType(
89
			TypeFactory.TypeScope scope,
90
			String entityName,
91
			String uniqueKeyPropertyName,
92
			boolean eager,
93
			boolean isEmbeddedInXML,
94
			boolean unwrapProxy) {
95
		this.scope = scope;
96
		this.associatedEntityName = entityName;
97
		this.uniqueKeyPropertyName = uniqueKeyPropertyName;
98
		this.isEmbeddedInXML = isEmbeddedInXML;
99
		this.eager = eager;
100
		this.unwrapProxy = unwrapProxy;
101
	}
102

  
103
	/**
104
	 * Constructs the requested entity type mapping.
105
	 *
106
	 * @param scope The type scope
107
	 * @param entityName The name of the associated entity.
108
	 * @param uniqueKeyPropertyName The property-ref name, or null if we
109
	 * reference the PK of the associated entity.
110
	 * @param eager Is eager fetching enabled.
111
	 * @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
112
	 * says to return the "implementation target" of lazy prooxies; typically only possible
113
	 * with lazy="no-proxy".
114
	 */
115
	protected EntityType(
116
			TypeFactory.TypeScope scope,
117
			String entityName,
118
			String uniqueKeyPropertyName,
119
			boolean eager,
120
			boolean unwrapProxy) {
121
		this.scope = scope;
122
		this.associatedEntityName = entityName;
123
		this.uniqueKeyPropertyName = uniqueKeyPropertyName;
124
		this.isEmbeddedInXML = true;
125
		this.eager = eager;
126
		this.unwrapProxy = unwrapProxy;
127
	}
128

  
129
	protected TypeFactory.TypeScope scope() {
130
		return scope;
131
	}
132

  
133
	/**
134
	 * An entity type is a type of association type
135
	 *
136
	 * @return True.
137
	 */
138
	@Override
139
    public boolean isAssociationType() {
140
		return true;
141
	}
142

  
143
	/**
144
	 * Explicitly, an entity type is an entity type ;)
145
	 *
146
	 * @return True.
147
	 */
148
	@Override
149
    public final boolean isEntityType() {
150
		return true;
151
	}
152

  
153
	/**
154
	 * {@inheritDoc}
155
	 */
156
	@Override
157
    public boolean isMutable() {
158
		return false;
159
	}
160

  
161
	/**
162
	 * Generates a string representation of this type.
163
	 *
164
	 * @return string rep
165
	 */
166
	@Override
167
    public String toString() {
168
		return getClass().getName() + '(' + getAssociatedEntityName() + ')';
169
	}
170

  
171
	/**
172
	 * For entity types, the name correlates to the associated entity name.
173
	 */
174
	@Override
175
    public String getName() {
176
		return associatedEntityName;
177
	}
178

  
179
	/**
180
	 * Does this association foreign key reference the primary key of the other table?
181
	 * Otherwise, it references a property-ref.
182
	 *
183
	 * @return True if this association reference the PK of the associated entity.
184
	 */
185
	public boolean isReferenceToPrimaryKey() {
186
		return uniqueKeyPropertyName==null;
187
	}
188

  
189
	@Override
190
    public String getRHSUniqueKeyPropertyName() {
191
		return uniqueKeyPropertyName;
192
	}
193

  
194
	@Override
195
    public String getLHSPropertyName() {
196
		return null;
197
	}
198

  
199
	public String getPropertyName() {
200
		return null;
201
	}
202

  
203
	/**
204
	 * The name of the associated entity.
205
	 *
206
	 * @return The associated entity name.
207
	 */
208
	public final String getAssociatedEntityName() {
209
		return associatedEntityName;
210
	}
211

  
212
	/**
213
	 * The name of the associated entity.
214
	 *
215
	 * @param factory The session factory, for resolution.
216
	 * @return The associated entity name.
217
	 */
218
	@Override
219
    public String getAssociatedEntityName(SessionFactoryImplementor factory) {
220
		return getAssociatedEntityName();
221
	}
222

  
223
	/**
224
	 * Retrieves the {@link Joinable} defining the associated entity.
225
	 *
226
	 * @param factory The session factory.
227
	 * @return The associated joinable
228
	 * @throws MappingException Generally indicates an invalid entity name.
229
	 */
230
	@Override
231
    public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException {
232
		return ( Joinable ) factory.getEntityPersister( associatedEntityName );
233
	}
234

  
235
	/**
236
	 * This returns the wrong class for an entity with a proxy, or for a named
237
	 * entity.  Theoretically it should return the proxy class, but it doesn't.
238
	 * <p/>
239
	 * The problem here is that we do not necessarily have a ref to the associated
240
	 * entity persister (nor to the session factory, to look it up) which is really
241
	 * needed to "do the right thing" here...
242
	 *
243
	 * @return The entiyt class.
244
	 */
245
	@Override
246
    public final Class getReturnedClass() {
247
		if ( returnedClass == null ) {
248
			returnedClass = determineAssociatedEntityClass();
249
		}
250
		return returnedClass;
251
	}
252

  
253
	private Class determineAssociatedEntityClass() {
254
		try {
255
			return ReflectHelper.classForName( getAssociatedEntityName() );
256
		}
257
		catch ( ClassNotFoundException cnfe ) {
258
			return java.util.Map.class;
259
		}
260
	}
261

  
262
	/**
263
	 * {@inheritDoc}
264
	 */
265
	@Override
266
    public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
267
	throws HibernateException, SQLException {
268
		return nullSafeGet( rs, new String[] {name}, session, owner );
269
	}
270

  
271
	/**
272
	 * {@inheritDoc}
273
	 */
274
	@Override
275
    public final Object nullSafeGet(
276
			ResultSet rs,
277
			String[] names,
278
			SessionImplementor session,
279
			Object owner) throws HibernateException, SQLException {
280
		return resolve( hydrate(rs, names, session, owner), session, owner );
281
	}
282

  
283
	/**
284
	 * Two entities are considered the same when their instances are the same.
285
	 *
286
	 *
287
	 * @param x One entity instance
288
	 * @param y Another entity instance
289
	 * @return True if x == y; false otherwise.
290
	 */
291
	@Override
292
    public final boolean isSame(Object x, Object y) {
293
		return x == y;
294
	}
295

  
296
	/**
297
	 * {@inheritDoc}
298
	 */
299
	@Override
300
    public int compare(Object x, Object y) {
301
		return 0; //TODO: entities CAN be compared, by PK, fix this! -> only if/when we can extract the id values....
302
	}
303

  
304
	/**
305
	 * {@inheritDoc}
306
	 */
307
	@Override
308
    public Object deepCopy(Object value, SessionFactoryImplementor factory) {
309
		return value; //special case ... this is the leaf of the containment graph, even though not immutable
310
	}
311

  
312
	/**
313
	 * {@inheritDoc}
314
	 */
315
	@Override
316
    public Object replace(
317
			Object original,
318
			Object target,
319
			SessionImplementor session,
320
			Object owner,
321
			Map copyCache) throws HibernateException {
322
		if ( original == null ) {
323
			return null;
324
		}
325
		Object cached = copyCache.get(original);
326
		if ( cached != null ) {
327
			return cached;
328
		}
329
		else {
330
			if ( original == target ) {
331
				return target;
332
			}
333
			if ( session.getContextEntityIdentifier( original ) == null  &&
334
					ForeignKeys.isTransient( associatedEntityName, original, Boolean.FALSE, session ) ) {
335
			    // final Object copy = session.getFactory().getEntityPersister( associatedEntityName )
336
                //  .instantiate( null, session );
337
			    // changed above call to below, because the associatedEntityName could be an abstract class
338
			    // in which case it cannot be instantiated
339

  
340
				final Object copy = session.getFactory().getEntityPersister( original.getClass().getName() )
341
						.instantiate( null, session );
342
				//TODO: should this be Session.instantiate(Persister, ...)?
343
				copyCache.put( original, copy );
344
				return copy;
345
			}
346
			else {
347
				Object id = getIdentifier( original, session );
348
				if ( id == null ) {
349
					throw new AssertionFailure("non-transient entity has a null id");
350
				}
351
				id = getIdentifierOrUniqueKeyType( session.getFactory() )
352
						.replace(id, null, session, owner, copyCache);
353
				return resolve( id, session, owner );
354
			}
355
		}
356
	}
357

  
358
	/**
359
	 * {@inheritDoc}
360
	 */
361
	@Override
362
    public int getHashCode(Object x, SessionFactoryImplementor factory) {
363
		EntityPersister persister = factory.getEntityPersister(associatedEntityName);
364
		if ( !persister.canExtractIdOutOfEntity() ) {
365
			return super.getHashCode( x );
366
		}
367

  
368
		final Serializable id;
369
		if (x instanceof HibernateProxy) {
370
			id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
371
		}
372
		else {
373
			final Class mappedClass = persister.getMappedClass();
374
			if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
375
				id = persister.getIdentifier( x );
376
			}
377
			else {
378
				id = (Serializable) x;
379
			}
380
		}
381
		return persister.getIdentifierType().getHashCode( id, factory );
382
	}
383

  
384
	@Override
385
	public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
386
		// associations (many-to-one and one-to-one) can be null...
387
		if ( x == null || y == null ) {
388
			return x == y;
389
		}
390

  
391
		EntityPersister persister = factory.getEntityPersister(associatedEntityName);
392
		if ( !persister.canExtractIdOutOfEntity() ) {
393
			return super.isEqual(x, y );
394
		}
395

  
396
		final Class mappedClass = persister.getMappedClass();
397
		Serializable xid;
398
		if (x instanceof HibernateProxy) {
399
			xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
400
					.getIdentifier();
401
		}
402
		else {
403
			if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
404
				xid = persister.getIdentifier( x );
405
			}
406
			else {
407
				//JPA 2 case where @IdClass contains the id and not the associated entity
408
				xid = (Serializable) x;
409
			}
410
		}
411

  
412
		Serializable yid;
413
		if (y instanceof HibernateProxy) {
414
			yid = ( (HibernateProxy) y ).getHibernateLazyInitializer()
415
					.getIdentifier();
416
		}
417
		else {
418
			if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
419
				yid = persister.getIdentifier( y );
420
			}
421
			else {
422
				//JPA 2 case where @IdClass contains the id and not the associated entity
423
				yid = (Serializable) y;
424
			}
425
		}
426

  
427
		return persister.getIdentifierType()
428
				.isEqual(xid, yid, factory);
429
	}
430

  
431
	/**
432
	 * {@inheritDoc}
433
	 */
434
	@Override
435
    public boolean isEmbeddedInXML() {
436
		return isEmbeddedInXML;
437
	}
438

  
439
	/**
440
	 * {@inheritDoc}
441
	 */
442
	@Override
443
    public boolean isXMLElement() {
444
		return isEmbeddedInXML;
445
	}
446

  
447
	/**
448
	 * {@inheritDoc}
449
	 */
450
	@Override
451
    public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
452
		if ( !isEmbeddedInXML ) {
453
			return getIdentifierType(factory).fromXMLNode(xml, factory);
454
		}
455
		else {
456
			return xml;
457
		}
458
	}
459

  
460
	/**
461
	 * {@inheritDoc}
462
	 */
463
	@Override
464
    public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
465
		if ( !isEmbeddedInXML ) {
466
			getIdentifierType(factory).setToXMLNode(node, value, factory);
467
		}
468
		else {
469
			Element elt = (Element) value;
470
			replaceNode( node, new ElementWrapper(elt) );
471
		}
472
	}
473

  
474
	@Override
475
    public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
476
	throws MappingException {
477
		if ( isReferenceToPrimaryKey() ) { //TODO: this is a bit arbitrary, expose a switch to the user?
478
			return "";
479
		}
480
		else {
481
			return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters );
482
		}
483
	}
484

  
485
	/**
486
	 * Resolve an identifier or unique key value
487
	 */
488
	@Override
489
    public Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
490
		if ( isNotEmbedded( session ) ) {
491
			return value;
492
		}
493

  
494
		if ( value == null ) {
495
			return null;
496
		}
497
		else {
498
			if ( isNull( owner, session ) ) {
499
				return null; //EARLY EXIT!
500
			}
501

  
502
			if ( isReferenceToPrimaryKey() ) {
503
				return resolveIdentifier( (Serializable) value, session );
504
			}
505
			else {
506
				return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
507
			}
508
		}
509
	}
510

  
511
	@Override
512
    public Type getSemiResolvedType(SessionFactoryImplementor factory) {
513
		return factory.getEntityPersister( associatedEntityName ).getIdentifierType();
514
	}
515

  
516
	protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
517
		if ( isNotEmbedded(session) ) {
518
			return value;
519
		}
520

  
521
		if ( isReferenceToPrimaryKey() ) {
522
			return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
523
		}
524
		else if ( value == null ) {
525
			return null;
526
		}
527
		else {
528
			EntityPersister entityPersister = session.getFactory().getEntityPersister( getAssociatedEntityName() );
529
			Object propertyValue = entityPersister.getPropertyValue( value, uniqueKeyPropertyName );
530
			// We now have the value of the property-ref we reference.  However,
531
			// we need to dig a little deeper, as that property might also be
532
			// an entity type, in which case we need to resolve its identitifier
533
			Type type = entityPersister.getPropertyType( uniqueKeyPropertyName );
534
			if ( type.isEntityType() ) {
535
				propertyValue = ( ( EntityType ) type ).getIdentifier( propertyValue, session );
536
			}
537

  
538
			return propertyValue;
539
		}
540
	}
541

  
542
	/**
543
	 * @deprecated To be removed in 5.  Removed as part of removing the notion of DOM entity-mode.
544
	 * See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
545
	 */
546
	@Deprecated
547
	protected boolean isNotEmbedded(SessionImplementor session) {
548
//		return !isEmbeddedInXML;
549
		return false;
550
	}
551

  
552
	/**
553
	 * Generate a loggable representation of an instance of the value mapped by this type.
554
	 *
555
	 * @param value The instance to be logged.
556
	 * @param factory The session factory.
557
	 * @return The loggable string.
558
	 * @throws HibernateException Generally some form of resolution problem.
559
	 */
560
	@Override
561
    public String toLoggableString(Object value, SessionFactoryImplementor factory) {
562
		if ( value == null ) {
563
			return "null";
564
		}
565

  
566
		EntityPersister persister = factory.getEntityPersister( associatedEntityName );
567
		StringBuilder result = new StringBuilder().append( associatedEntityName );
568

  
569
		if ( persister.hasIdentifierProperty() ) {
570
			final EntityMode entityMode = persister.getEntityMode();
571
			final Serializable id;
572
			if ( entityMode == null ) {
573
				if ( isEmbeddedInXML ) {
574
					throw new ClassCastException( value.getClass().getName() );
575
				}
576
				id = ( Serializable ) value;
577
			} else if ( value instanceof HibernateProxy ) {
578
				HibernateProxy proxy = ( HibernateProxy ) value;
579
				id = proxy.getHibernateLazyInitializer().getIdentifier();
580
			}
581
			else {
582
				id = persister.getIdentifier( value );
583
			}
584

  
585
			result.append( '#' )
586
				.append( persister.getIdentifierType().toLoggableString( id, factory ) );
587
		}
588

  
589
		return result.toString();
590
	}
591

  
592
	/**
593
	 * Is the association modeled here defined as a 1-1 in the database (physical model)?
594
	 *
595
	 * @return True if a 1-1 in the database; false otherwise.
596
	 */
597
	public abstract boolean isOneToOne();
598

  
599
	/**
600
	 * Is the association modeled here a 1-1 according to the logical moidel?
601
	 *
602
	 * @return True if a 1-1 in the logical model; false otherwise.
603
	 */
604
	public boolean isLogicalOneToOne() {
605
		return isOneToOne();
606
	}
607

  
608
	/**
609
	 * Convenience method to locate the identifier type of the associated entity.
610
	 *
611
	 * @param factory The mappings...
612
	 * @return The identifier type
613
	 */
614
	Type getIdentifierType(Mapping factory) {
615
		return factory.getIdentifierType( getAssociatedEntityName() );
616
	}
617

  
618
	/**
619
	 * Convenience method to locate the identifier type of the associated entity.
620
	 *
621
	 * @param session The originating session
622
	 * @return The identifier type
623
	 */
624
	Type getIdentifierType(SessionImplementor session) {
625
		return getIdentifierType( session.getFactory() );
626
	}
627

  
628
	/**
629
	 * Determine the type of either (1) the identifier if we reference the
630
	 * associated entity's PK or (2) the unique key to which we refer (i.e.
631
	 * the property-ref).
632
	 *
633
	 * @param factory The mappings...
634
	 * @return The appropriate type.
635
	 * @throws MappingException Generally, if unable to resolve the associated entity name
636
	 * or unique key property name.
637
	 */
638
	public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
639
		if ( isReferenceToPrimaryKey() ) {
640
			return getIdentifierType(factory);
641
		}
642
		else {
643
			Type type = factory.getReferencedPropertyType( getAssociatedEntityName(), uniqueKeyPropertyName );
644
			if ( type.isEntityType() ) {
645
				type = ( ( EntityType ) type).getIdentifierOrUniqueKeyType( factory );
646
			}
647
			return type;
648
		}
649
	}
650

  
651
	/**
652
	 * The name of the property on the associated entity to which our FK
653
	 * refers
654
	 *
655
	 * @param factory The mappings...
656
	 * @return The appropriate property name.
657
	 * @throws MappingException Generally, if unable to resolve the associated entity name
658
	 */
659
	public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
660
	throws MappingException {
661
		if ( isReferenceToPrimaryKey() ) {
662
			return factory.getIdentifierPropertyName( getAssociatedEntityName() );
663
		}
664
		else {
665
			return uniqueKeyPropertyName;
666
		}
667
	}
668

  
669
	protected abstract boolean isNullable();
670

  
671
	/**
672
	 * Resolve an identifier via a load.
673
	 *
674
	 * @param id The entity id to resolve
675
	 * @param session The orginating session.
676
	 * @return The resolved identifier (i.e., loaded entity).
677
	 * @throws org.hibernate.HibernateException Indicates problems performing the load.
678
	 */
679
	protected final Object resolveIdentifier(Serializable id, SessionImplementor session) throws HibernateException {
680
		boolean isProxyUnwrapEnabled = unwrapProxy &&
681
				session.getFactory()
682
						.getEntityPersister( getAssociatedEntityName() )
683
						.isInstrumented();
684

  
685
		Object proxyOrEntity = session.internalLoad(
686
				getAssociatedEntityName(),
687
				id,
688
				eager,
689
				isNullable() && !isProxyUnwrapEnabled
690
		);
691

  
692
		if ( proxyOrEntity instanceof HibernateProxy ) {
693
			( ( HibernateProxy ) proxyOrEntity ).getHibernateLazyInitializer()
694
					.setUnwrap( isProxyUnwrapEnabled );
695
		}
696

  
697
		return proxyOrEntity;
698
	}
699

  
700
	protected boolean isNull(Object owner, SessionImplementor session) {
701
		return false;
702
	}
703

  
704
	/**
705
	 * Load an instance by a unique key that is not the primary key.
706
	 *
707
	 * @param entityName The name of the entity to load
708
	 * @param uniqueKeyPropertyName The name of the property defining the uniqie key.
709
	 * @param key The unique key property value.
710
	 * @param session The originating session.
711
	 * @return The loaded entity
712
	 * @throws HibernateException generally indicates problems performing the load.
713
	 */
714
	public Object loadByUniqueKey(
715
			String entityName,
716
			String uniqueKeyPropertyName,
717
			Object key,
718
			SessionImplementor session) throws HibernateException {
719
		final SessionFactoryImplementor factory = session.getFactory();
720
		UniqueKeyLoadable persister = ( UniqueKeyLoadable ) factory.getEntityPersister( entityName );
721

  
722
		//TODO: implement caching?! proxies?!
723

  
724
		EntityUniqueKey euk = new EntityUniqueKey(
725
				entityName,
726
				uniqueKeyPropertyName,
727
				key,
728
				getIdentifierOrUniqueKeyType( factory ),
729
				persister.getEntityMode(),
730
				session.getFactory()
731
		);
732

  
733
		final PersistenceContext persistenceContext = session.getPersistenceContext();
734
		Object result = persistenceContext.getEntity( euk );
735
		if ( result == null ) {
736
			result = persister.loadByUniqueKey( uniqueKeyPropertyName, key, session );
737
		}
738
		return result == null ? null : persistenceContext.proxyFor( result );
739
	}
740

  
741
}

Also available in: Unified diff