Merge remote-tracking branch 'origin/master' into metamodel

Conflicts:
	hibernate-core/src/main/java/org/hibernate/LockOptions.java
	hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCacheEntry.java
	hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCollectionCacheEntry.java
	hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredMapCacheEntry.java
	hibernate-core/src/main/java/org/hibernate/cache/spi/entry/UnstructuredCacheEntry.java
	hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java
	hibernate-core/src/main/java/org/hibernate/id/TableGenerator.java
	hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java
	hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
	hibernate-core/src/main/java/org/hibernate/metamodel/relational/Database.java
	hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java
	hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/HibernateTypeResolver.java
	hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Index.java
	hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/UniqueKey.java
	hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
	hibernate-core/src/main/java/org/hibernate/type/ArrayType.java
	hibernate-core/src/main/java/org/hibernate/type/Type.java
	hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/UniqueConstraintTest.java
	hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java
	hibernate-core/src/test/java/org/hibernate/test/criterion/CriterionTest.java
	hibernate-core/src/test/resources/org/hibernate/test/propertyref/inheritence/union/Person.hbm.xml
	hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
This commit is contained in:
Brett Meyer 2012-12-20 00:09:45 -05:00
commit c33fdae563
157 changed files with 3547 additions and 908 deletions

View File

@ -898,7 +898,9 @@ query.add(AuditEntity.relatedId("address").eq(relatedEntityId));]]></programlist
<para>
The <literal>minimize()</literal> and <literal>maximize()</literal> methods return a criteria,
to which you can add constraints, which must be met by the entities with the
maximized/minimized properties.
maximized/minimized properties. <literal>AggregatedAuditExpression#computeAggregationInInstanceContext()</literal>
enables the possibility to compute aggregated expression in the context of each entity instance
separately. It turns out useful when querying for latest revisions of all entities of a particular type.
</para>
<para>

View File

@ -15,7 +15,7 @@
<term>Optimistic</term>
<listitem>
<para>
Optimistic locking ssumes that multiple transactions can complete without affecting each other, and that
Optimistic locking assumes that multiple transactions can complete without affecting each other, and that
therefore transactions can proceed without locking the data resources that they affect. Before committing,
each transaction verifies that no other transaction has modified its data. If the check reveals conflicting
modifications, the committing transaction rolls back<footnote><para><link xl:href="http://en.wikipedia.org/wiki/Optimistic_locking" /></para></footnote>.

View File

@ -69,11 +69,11 @@ public class AuditInterceptor extends EmptyInterceptor {
public void afterTransactionCompletion(Transaction tx) {
if ( tx.wasCommitted() ) {
System.out.println("Creations: " + creates + ", Updates: " + updates, "Loads: " + loads);
System.out.println("Creations: " + creates + ", Updates: " + updates + "Loads: " + loads);
}
updates=0;
creates=0;
loads=0;
}
}
}

View File

@ -18,6 +18,6 @@ public class MyIntegrator implements org.hibernate.integrator.spi.Integrator {
// 2) This form adds the specified listener(s) to the beginning of the listener chain
eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledFirst );
// 3) This form adds the specified listener(s) to the end of the listener chain
eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast );
eventListenerRegistry.appendListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast );
}
}
}

View File

@ -3,9 +3,9 @@ Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
int updatedEntities = session.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
session.close();

View File

@ -2,7 +2,7 @@ Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
int createdEntities = session.createQuery( hqlInsert )
.executeUpdate();
tx.commit();
session.close();
session.close();

View File

@ -3,8 +3,8 @@ Transaction tx = session.beginTransaction();
String hqlDelete = "delete Customer c where c.name = :oldName";
// or String hqlDelete = "delete Customer where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
int deletedEntities = session.createQuery( hqlDelete )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
session.close();

View File

@ -1,9 +1,9 @@
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
int updatedEntities = session.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
session.close();

View File

@ -184,7 +184,7 @@ create table Address ( addressId bigint not null primary key, personId bigint no
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId not null, addressId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )
]]></programlisting>

View File

@ -102,7 +102,7 @@ public class AuditInterceptor extends EmptyInterceptor {
public void afterTransactionCompletion(Transaction tx) {
if ( tx.wasCommitted() ) {
System.out.println("Creations: " + creates + ", Updates: " + updates, "Loads: " + loads);
System.out.println("Creations: " + creates + ", Updates: " + updates + "Loads: " + loads);
}
updates=0;
creates=0;

View File

@ -49,6 +49,7 @@ public class LockOptions implements Serializable {
* UPGRADE represents LockMode.UPGRADE (will wait forever for lock and
* scope of false meaning only entity is locked)
*/
@SuppressWarnings("deprecation")
public static final LockOptions UPGRADE = new LockOptions(LockMode.UPGRADE);
/**
@ -65,7 +66,9 @@ public class LockOptions implements Serializable {
private LockMode lockMode = LockMode.NONE;
private int timeout = WAIT_FOREVER;
private Map<String, LockMode> aliasSpecificLockModes = null; //initialize lazily as LockOptions is frequently created without needing this
//initialize lazily as LockOptions is frequently created without needing this
private Map<String,LockMode> aliasSpecificLockModes = null;
public LockOptions() {
}
@ -114,7 +117,7 @@ public class LockOptions implements Serializable {
*/
public LockOptions setAliasSpecificLockMode(String alias, LockMode lockMode) {
if ( aliasSpecificLockModes == null ) {
aliasSpecificLockModes = new HashMap<String, LockMode>();
aliasSpecificLockModes = new HashMap<String,LockMode>();
}
aliasSpecificLockModes.put( alias, lockMode );
return this;
@ -159,6 +162,11 @@ public class LockOptions implements Serializable {
return lockMode == null ? LockMode.NONE : lockMode;
}
public boolean hasAliasSpecificLockModes() {
return aliasSpecificLockModes != null
&& ! aliasSpecificLockModes.isEmpty();
}
/**
* Get the number of aliases that have specific lock modes defined.
*
@ -183,6 +191,30 @@ public class LockOptions implements Serializable {
return aliasSpecificLockModes.entrySet().iterator();
}
/**
* Currently needed for follow-on locking
*
* @return The greatest of all requested lock modes.
*/
public LockMode findGreatestLockMode() {
LockMode lockModeToUse = getLockMode();
if ( lockModeToUse == null ) {
lockModeToUse = LockMode.NONE;
}
if ( aliasSpecificLockModes == null ) {
return lockModeToUse;
}
for ( LockMode lockMode : aliasSpecificLockModes.values() ) {
if ( lockMode.greaterThan( lockModeToUse ) ) {
lockModeToUse = lockMode;
}
}
return lockModeToUse;
}
/**
* Retrieve the current timeout setting.
* <p/>
@ -245,19 +277,20 @@ public class LockOptions implements Serializable {
}
/**
* Shallow copy From to Dest
* Perform a shallow copy
*
* @param from is copied from
* @param dest is copied to
* @return dest
* @param source Source for the copy (copied from)
* @param destination Destination for the copy (copied to)
*
* @return destination
*/
public static LockOptions copy(LockOptions from, LockOptions dest) {
dest.setLockMode(from.getLockMode());
dest.setScope(from.getScope());
dest.setTimeOut(from.getTimeOut());
if ( from.aliasSpecificLockModes != null ) {
dest.aliasSpecificLockModes = new HashMap<String, LockMode>( from.aliasSpecificLockModes );
public static LockOptions copy(LockOptions source, LockOptions destination) {
destination.setLockMode( source.getLockMode() );
destination.setScope( source.getScope() );
destination.setTimeOut( source.getTimeOut() );
if ( source.aliasSpecificLockModes != null ) {
destination.aliasSpecificLockModes = new HashMap<String,LockMode>( source.aliasSpecificLockModes );
}
return dest;
return destination;
}
}

View File

@ -65,7 +65,7 @@ public interface SimpleNaturalIdLoadAccess {
*
* @param naturalIdValue The value of the natural-id for the entity to retrieve
*
* @return the persistent instance or proxy
* @return The persistent instance or proxy, if an instance exists. Otherwise, {@code null}.
*/
public Object getReference(Object naturalIdValue);

View File

@ -108,16 +108,12 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
final SessionFactoryImplementor factory = getSession().getFactory();
if ( isCachePutEnabled( persister, session ) ) {
CacheEntry ce = new CacheEntry(
CacheEntry ce = persister.buildCacheEntry(
instance,
getState(),
persister,
persister.hasUninitializedLazyProperties( instance ),
version,
session,
instance
);
session
);
cacheEntry = persister.getCacheEntryStructure().structure(ce);
final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );

View File

@ -185,14 +185,7 @@ public final class EntityUpdateAction extends EntityAction {
}
else {
//TODO: inefficient if that cache is just going to ignore the updated state!
CacheEntry ce = new CacheEntry(
state,
persister,
persister.hasUninitializedLazyProperties( instance ),
nextVersion,
getSession(),
instance
);
CacheEntry ce = persister.buildCacheEntry( instance,state, nextVersion, getSession() );
cacheEntry = persister.getCacheEntryStructure().structure( ce );
boolean put = persister.getCacheAccessStrategy().update( ck, cacheEntry, nextVersion, previousVersion );
if ( put && factory.getStatistics().isStatisticsEnabled() ) {

View File

@ -31,9 +31,11 @@ import javassist.CannotCompileException;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.Opcode;
import javassist.bytecode.StackMapTable;
import javassist.util.proxy.FactoryHelper;
import javassist.util.proxy.RuntimeSupport;
@ -244,6 +246,7 @@ class BulkAccessorFactory {
MethodInfo mi = new MethodInfo( cp, GENERATED_SETTER_NAME, desc );
Bytecode code = new Bytecode( cp, 4, 6 );
StackMapTable stackmap = null;
/* | this | bean | args | i | raw bean | exception | */
if ( setters.length > 0 ) {
int start, end; // required to exception table
@ -321,7 +324,8 @@ class BulkAccessorFactory {
/* current stack len = 0 */
// register in exception table
int throwableType_index = cp.addClassInfo( THROWABLE_CLASS_NAME );
code.addExceptionHandler( start, end, code.currentPc(), throwableType_index );
int handler_pc = code.currentPc();
code.addExceptionHandler( start, end, handler_pc, throwableType_index );
// astore 5 // store exception
code.addAstore( 5 );
// new // BulkAccessorException
@ -337,13 +341,24 @@ class BulkAccessorFactory {
code.addInvokespecial( BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, cons_desc );
// athrow
code.addOpcode( Opcode.ATHROW );
StackMapTable.Writer writer = new StackMapTable.Writer(32);
int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
int[] localData = { cp.getThisClassInfo(), cp.addClassInfo("java/lang/Object"),
cp.addClassInfo("[Ljava/lang/Object;"), 0};
int[] stackTags = { StackMapTable.OBJECT };
int[] stackData = { throwableType_index };
writer.fullFrame(handler_pc, localTags, localData, stackTags, stackData);
stackmap = writer.toStackMapTable(cp);
}
else {
// return
code.addOpcode( Opcode.RETURN );
}
mi.setCodeAttribute( code.toCodeAttribute() );
CodeAttribute ca = code.toCodeAttribute();
if (stackmap != null) {
ca.setAttribute(stackmap);
}
mi.setCodeAttribute( ca );
mi.setAccessFlags( AccessFlag.PUBLIC );
classfile.addMethod( mi );
}

View File

@ -32,6 +32,7 @@ import java.util.Iterator;
import java.util.List;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.Bytecode;
@ -43,6 +44,8 @@ import javassist.bytecode.Descriptor;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.Opcode;
import javassist.bytecode.StackMapTable;
import javassist.bytecode.stackmap.MapMaker;
/**
* The thing that handles actual class enhancement in regards to
@ -50,6 +53,7 @@ import javassist.bytecode.Opcode;
*
* @author Muga Nishizawa
* @author Steve Ebersole
* @author Dustin Schultz
*/
public class FieldTransformer {
@ -79,13 +83,20 @@ public class FieldTransformer {
+ HANDLER_FIELD_DESCRIPTOR + ")V";
private FieldFilter filter;
private ClassPool classPool;
public FieldTransformer() {
this(null);
this(null, null);
}
public FieldTransformer(FieldFilter f) {
public FieldTransformer(FieldFilter f, ClassPool c) {
filter = f;
classPool = c;
}
public void setClassPool(ClassPool c) {
classPool = c;
}
public void setFieldFilter(FieldFilter f) {
@ -130,7 +141,7 @@ public class FieldTransformer {
}
private void addGetFieldHandlerMethod(ClassFile classfile)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
ConstPool cp = classfile.getConstPool();
int this_class_index = cp.getThisClassInfo();
MethodInfo minfo = new MethodInfo(cp, GETFIELDHANDLER_METHOD_NAME,
@ -148,11 +159,16 @@ public class FieldTransformer {
code.addOpcode(Opcode.ARETURN);
minfo.setCodeAttribute(code.toCodeAttribute());
minfo.setAccessFlags(AccessFlag.PUBLIC);
CodeAttribute codeAttribute = minfo.getCodeAttribute();
if (codeAttribute != null) {
StackMapTable smt = MapMaker.make(classPool, minfo);
codeAttribute.setAttribute(smt);
}
classfile.addMethod(minfo);
}
private void addSetFieldHandlerMethod(ClassFile classfile)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
ConstPool cp = classfile.getConstPool();
int this_class_index = cp.getThisClassInfo();
MethodInfo minfo = new MethodInfo(cp, SETFIELDHANDLER_METHOD_NAME,
@ -172,6 +188,11 @@ public class FieldTransformer {
code.addOpcode(Opcode.RETURN);
minfo.setCodeAttribute(code.toCodeAttribute());
minfo.setAccessFlags(AccessFlag.PUBLIC);
CodeAttribute codeAttribute = minfo.getCodeAttribute();
if (codeAttribute != null) {
StackMapTable smt = MapMaker.make(classPool, minfo);
codeAttribute.setAttribute(smt);
}
classfile.addMethod(minfo);
}
@ -185,7 +206,7 @@ public class FieldTransformer {
}
private void addReadWriteMethods(ClassFile classfile)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
List fields = classfile.getFields();
for (Iterator field_iter = fields.iterator(); field_iter.hasNext();) {
FieldInfo finfo = (FieldInfo) field_iter.next();
@ -205,7 +226,7 @@ public class FieldTransformer {
}
private void addReadMethod(ClassFile classfile, FieldInfo finfo)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
ConstPool cp = classfile.getConstPool();
int this_class_index = cp.getThisClassInfo();
String desc = "()" + finfo.getDescriptor();
@ -254,11 +275,16 @@ public class FieldTransformer {
minfo.setCodeAttribute(code.toCodeAttribute());
minfo.setAccessFlags(AccessFlag.PUBLIC);
CodeAttribute codeAttribute = minfo.getCodeAttribute();
if (codeAttribute != null) {
StackMapTable smt = MapMaker.make(classPool, minfo);
codeAttribute.setAttribute(smt);
}
classfile.addMethod(minfo);
}
private void addWriteMethod(ClassFile classfile, FieldInfo finfo)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
ConstPool cp = classfile.getConstPool();
int this_class_index = cp.getThisClassInfo();
String desc = "(" + finfo.getDescriptor() + ")V";
@ -320,11 +346,16 @@ public class FieldTransformer {
minfo.setCodeAttribute(code.toCodeAttribute());
minfo.setAccessFlags(AccessFlag.PUBLIC);
CodeAttribute codeAttribute = minfo.getCodeAttribute();
if (codeAttribute != null) {
StackMapTable smt = MapMaker.make(classPool, minfo);
codeAttribute.setAttribute(smt);
}
classfile.addMethod(minfo);
}
private void transformInvokevirtualsIntoPutAndGetfields(ClassFile classfile)
throws CannotCompileException {
throws CannotCompileException, BadBytecode {
List methods = classfile.getMethods();
for (Iterator method_iter = methods.iterator(); method_iter.hasNext();) {
MethodInfo minfo = (MethodInfo) method_iter.next();
@ -341,15 +372,12 @@ public class FieldTransformer {
}
CodeIterator iter = codeAttr.iterator();
while (iter.hasNext()) {
try {
int pos = iter.next();
pos = transformInvokevirtualsIntoGetfields(classfile, iter, pos);
pos = transformInvokevirtualsIntoPutfields(classfile, iter, pos);
} catch ( BadBytecode e ){
throw new CannotCompileException( e );
}
int pos = iter.next();
pos = transformInvokevirtualsIntoGetfields(classfile, iter, pos);
pos = transformInvokevirtualsIntoPutfields(classfile, iter, pos);
}
StackMapTable smt = MapMaker.make(classPool, minfo);
codeAttr.setAttribute(smt);
}
}

View File

@ -30,6 +30,8 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.security.ProtectionDomain;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.bytecode.ClassFile;
import org.jboss.logging.Logger;
@ -44,6 +46,7 @@ import org.hibernate.internal.CoreMessageLogger;
*
* @author Emmanuel Bernard
* @author Steve Ebersole
* @author Dustin Schultz
*/
public class JavassistClassTransformer extends AbstractClassTransformerImpl {
@ -70,7 +73,17 @@ public class JavassistClassTransformer extends AbstractClassTransformerImpl {
LOG.unableToBuildEnhancementMetamodel( className );
return classfileBuffer;
}
FieldTransformer transformer = getFieldTransformer( classfile );
// This is the same as ClassPool.getDefault() but ensures a new ClassPool per
ClassPool cp = new ClassPool();
cp.appendSystemPath();
cp.appendClassPath(new ClassClassPath(this.getClass()));
cp.appendClassPath(new ClassClassPath(classfile.getClass()));
try {
cp.makeClassIfNew(new ByteArrayInputStream(classfileBuffer));
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
FieldTransformer transformer = getFieldTransformer( classfile, cp );
if ( transformer != null ) {
LOG.debugf( "Enhancing %s", className );
DataOutputStream out = null;
@ -97,7 +110,7 @@ public class JavassistClassTransformer extends AbstractClassTransformerImpl {
return classfileBuffer;
}
protected FieldTransformer getFieldTransformer(final ClassFile classfile) {
protected FieldTransformer getFieldTransformer(final ClassFile classfile, final ClassPool classPool) {
if ( alreadyInstrumented( classfile ) ) {
return null;
}
@ -118,7 +131,7 @@ public class JavassistClassTransformer extends AbstractClassTransformerImpl {
public boolean handleWriteAccess(String fieldOwnerClassName, String fieldName) {
return fieldFilter.shouldTransformFieldAccess( classfile.getName(), fieldOwnerClassName, fieldName );
}
}
}, classPool
);
}

View File

@ -25,137 +25,41 @@ package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.TypeHelper;
/**
* A cached instance of a persistent class
*
* @author Gavin King
* @author Steve Ebersole
*/
public final class CacheEntry implements Serializable {
public interface CacheEntry extends Serializable {
public boolean isReferenceEntry();
private final Serializable[] disassembledState;
private final String subclass;
private final boolean lazyPropertiesAreUnfetched;
private final Object version;
public String getSubclass() {
return subclass;
}
public boolean areLazyPropertiesUnfetched() {
return lazyPropertiesAreUnfetched;
}
public CacheEntry(
final Object[] state,
final EntityPersister persister,
final boolean unfetched,
final Object version,
final SessionImplementor session,
final Object owner)
throws HibernateException {
//disassembled state gets put in a new array (we write to cache by value!)
this.disassembledState = TypeHelper.disassemble(
state,
persister.getPropertyTypes(),
persister.isLazyPropertiesCacheable() ?
null : persister.getPropertyLaziness(),
session,
owner
);
subclass = persister.getEntityName();
lazyPropertiesAreUnfetched = unfetched || !persister.isLazyPropertiesCacheable();
this.version = version;
}
public Object getVersion() {
return version;
}
/**
* Hibernate stores all entries pertaining to a given entity hierarchy in a single region. This attribute
* tells us the specific entity type represented by the cached data.
*
* @return The entry's exact entity type.
*/
public String getSubclass();
CacheEntry(Serializable[] state, String subclass, boolean unfetched, Object version) {
this.disassembledState = state;
this.subclass = subclass;
this.lazyPropertiesAreUnfetched = unfetched;
this.version = version;
}
/**
* Retrieves the version (optimistic locking) associated with this cache entry.
*
* @return The version of the entity represented by this entry
*/
public Object getVersion();
public Object[] assemble(
final Object instance,
final Serializable id,
final EntityPersister persister,
final Interceptor interceptor,
final EventSource session)
throws HibernateException {
public boolean areLazyPropertiesUnfetched();
if ( !persister.getEntityName().equals(subclass) ) {
throw new AssertionFailure("Tried to assemble a different subclass instance");
}
return assemble(disassembledState, instance, id, persister, interceptor, session);
}
private static Object[] assemble(
final Serializable[] values,
final Object result,
final Serializable id,
final EntityPersister persister,
final Interceptor interceptor,
final EventSource session) throws HibernateException {
//assembled state gets put in a new array (we read from cache by value!)
Object[] assembledProps = TypeHelper.assemble(
values,
persister.getPropertyTypes(),
session, result
);
//persister.setIdentifier(result, id); //before calling interceptor, for consistency with normal load
//TODO: reuse the PreLoadEvent
final PreLoadEvent preLoadEvent = new PreLoadEvent( session )
.setEntity( result )
.setState( assembledProps )
.setId( id )
.setPersister( persister );
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD );
for ( PreLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPreLoad( preLoadEvent );
}
persister.setPropertyValues( result, assembledProps );
return assembledProps;
}
public Serializable[] getDisassembledState() {
// todo: this was added to support initializing an entity's EntityEntry snapshot during reattach;
// this should be refactored to instead expose a method to assemble a EntityEntry based on this
// state for return.
return disassembledState;
}
public String toString() {
return "CacheEntry(" + subclass + ')' + ArrayHelper.toString(disassembledState);
}
// todo: this was added to support initializing an entity's EntityEntry snapshot during reattach;
// this should be refactored to instead expose a method to assemble a EntityEntry based on this
// state for return.
public Serializable[] getDisassembledState();
}

View File

@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import org.hibernate.Interceptor;
import org.hibernate.event.spi.EventSource;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class ReferenceCacheEntryImpl implements CacheEntry {
private final Object reference;
private final String subclass;
public ReferenceCacheEntryImpl(Object reference, String subclass) {
this.reference = reference;
this.subclass = subclass;
}
@Override
public boolean isReferenceEntry() {
return true;
}
@Override
public String getSubclass() {
return subclass;
}
@Override
public Object getVersion() {
// reference data cannot be versioned
return null;
}
@Override
public boolean areLazyPropertiesUnfetched() {
// reference data cannot define lazy attributes
return false;
}
@Override
public Serializable[] getDisassembledState() {
// reference data is not disassembled into the cache
return null;
}
public Object getReference() {
return reference;
}
}

View File

@ -0,0 +1,170 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.TypeHelper;
/**
* @author Steve Ebersole
*/
public class StandardCacheEntryImpl implements CacheEntry {
private final Serializable[] disassembledState;
private final String subclass;
private final boolean lazyPropertiesAreUnfetched;
private final Object version;
@Override
public boolean isReferenceEntry() {
return false;
}
@Override
public Serializable[] getDisassembledState() {
// todo: this was added to support initializing an entity's EntityEntry snapshot during reattach;
// this should be refactored to instead expose a method to assemble a EntityEntry based on this
// state for return.
return disassembledState;
}
@Override
public String getSubclass() {
return subclass;
}
@Override
public boolean areLazyPropertiesUnfetched() {
return lazyPropertiesAreUnfetched;
}
@Override
public Object getVersion() {
return version;
}
public StandardCacheEntryImpl(
final Object[] state,
final EntityPersister persister,
final boolean unfetched,
final Object version,
final SessionImplementor session,
final Object owner)
throws HibernateException {
//disassembled state gets put in a new array (we write to cache by value!)
this.disassembledState = TypeHelper.disassemble(
state,
persister.getPropertyTypes(),
persister.isLazyPropertiesCacheable() ?
null : persister.getPropertyLaziness(),
session,
owner
);
subclass = persister.getEntityName();
lazyPropertiesAreUnfetched = unfetched || !persister.isLazyPropertiesCacheable();
this.version = version;
}
StandardCacheEntryImpl(Serializable[] state, String subclass, boolean unfetched, Object version) {
this.disassembledState = state;
this.subclass = subclass;
this.lazyPropertiesAreUnfetched = unfetched;
this.version = version;
}
public boolean isDeepCopyNeeded() {
// for now always return true.
// todo : See discussion on HHH-7872
return true;
}
public Object[] assemble(
final Object instance,
final Serializable id,
final EntityPersister persister,
final Interceptor interceptor,
final EventSource session)
throws HibernateException {
if ( !persister.getEntityName().equals(subclass) ) {
throw new AssertionFailure("Tried to assemble a different subclass instance");
}
return assemble(disassembledState, instance, id, persister, interceptor, session);
}
private static Object[] assemble(
final Serializable[] values,
final Object result,
final Serializable id,
final EntityPersister persister,
final Interceptor interceptor,
final EventSource session) throws HibernateException {
//assembled state gets put in a new array (we read from cache by value!)
Object[] assembledProps = TypeHelper.assemble(
values,
persister.getPropertyTypes(),
session, result
);
//persister.setIdentifier(result, id); //before calling interceptor, for consistency with normal load
//TODO: reuse the PreLoadEvent
final PreLoadEvent preLoadEvent = new PreLoadEvent( session )
.setEntity( result )
.setState( assembledProps )
.setId( id )
.setPersister( persister );
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.PRE_LOAD );
for ( PreLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPreLoad( preLoadEvent );
}
persister.setPropertyValues( result, assembledProps );
return assembledProps;
}
public String toString() {
return "CacheEntry(" + subclass + ')' + ArrayHelper.toString( disassembledState );
}
}

View File

@ -31,7 +31,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
/**
* Structured CacheEntry format for entities. Used to store the entry into the second-level cache
* as a Map so that users can more easily see the cached state.
*
* @author Gavin King
* @author Steve Ebersole
*/
public class StructuredCacheEntry implements CacheEntryStructure<CacheEntry, Map> {
@ -52,7 +56,7 @@ public class StructuredCacheEntry implements CacheEntryStructure<CacheEntry, Map
for ( int i = 0; i < names.length; i++ ) {
state[i] = (Serializable) map.get( names[i] );
}
return new CacheEntry( state, subclass, lazyPropertiesUnfetched, version );
return new StandardCacheEntryImpl( state, subclass, lazyPropertiesUnfetched, version );
}
@Override

View File

@ -30,9 +30,7 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
* For other plural attributes except map, this impl is used.
* </br>
* Internally, a list that contains all collection states is stored into 2LC.
* Structured CacheEntry format for persistent collections (other than Maps, see {@link StructuredMapCacheEntry}).
*
* @author Gavin King
*/

View File

@ -25,13 +25,12 @@ package org.hibernate.cache.spi.entry;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
* (De)structure the map type collection attribute that is being cached into 2LC.
* Structured CacheEntry format for persistent Maps.
*
* @author Gavin King
*/

View File

@ -26,18 +26,14 @@ package org.hibernate.cache.spi.entry;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
* The very simple implementation of {@code CacheEntryStructure} that doing nothing but just return what it get.
*
* </br>
*
* This is used when {@link org.hibernate.cfg.AvailableSettings#USE_STRUCTURED_CACHE} is set to {@code false}.
*
* NOTE: This property is set to {@code false} by default.
* Unstructured CacheEntry format (used to store entities and collections).
*
* @author Gavin King
* @author Steve Ebersole
*/
public class UnstructuredCacheEntry implements CacheEntryStructure<Object, Object> {
@Override
public class UnstructuredCacheEntry implements CacheEntryStructure {
public static final UnstructuredCacheEntry INSTANCE = new UnstructuredCacheEntry();
public Object structure(Object item) {
return item;
}

View File

@ -652,4 +652,10 @@ public interface AvailableSettings {
* {@link org.hibernate.loader.BatchFetchStyle} instance.
*/
public static final String BATCH_FETCH_STYLE = "hibernate.batch_fetch_style";
/**
* Enable direct storage of entity references into the second level cache when applicable (immutable data, etc).
* Default is to not store direct references.
*/
public static final String USE_DIRECT_REFERENCE_CACHE_ENTRIES = "hibernate.cache.use_reference_entries";
}

View File

@ -51,6 +51,7 @@ import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import javax.persistence.AttributeConverter;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
@ -60,10 +61,6 @@ import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.jboss.logging.Logger;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.DuplicateMappingException;
@ -82,6 +79,7 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.Dialect;
@ -137,7 +135,6 @@ import org.hibernate.mapping.UniqueKey;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.internal.JACCConfiguration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.hibernate.tool.hbm2ddl.IndexMetadata;
import org.hibernate.tool.hbm2ddl.TableMetadata;
@ -148,6 +145,9 @@ import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.UserType;
import org.jboss.logging.Logger;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* An instance of <tt>Configuration</tt> allows the application
@ -1049,17 +1049,15 @@ public class Configuration implements Serializable {
Table table = (Table) iter.next();
if ( table.isPhysicalTable() ) {
if ( !dialect.supportsUniqueConstraintInCreateAlterTable() ) {
Iterator subIter = table.getUniqueKeyIterator();
while ( subIter.hasNext() ) {
UniqueKey uk = (UniqueKey) subIter.next();
String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema );
if (constraintString != null) script.add( constraintString );
}
Iterator subIter = table.getUniqueKeyIterator();
while ( subIter.hasNext() ) {
UniqueKey uk = (UniqueKey) subIter.next();
String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema );
if (constraintString != null) script.add( constraintString );
}
Iterator subIter = table.getIndexIterator();
subIter = table.getIndexIterator();
while ( subIter.hasNext() ) {
Index index = (Index) subIter.next();
script.add(
@ -1230,15 +1228,6 @@ public class Configuration implements Serializable {
)
);
}
//broken, 'cos we don't generate these with names in SchemaExport
// subIter = table.getUniqueKeyIterator();
// while ( subIter.hasNext() ) {
// UniqueKey uk = (UniqueKey) subIter.next();
// if ( tableInfo==null || tableInfo.getIndexMetadata( uk.getFilterName() ) == null ) {
// script.add( uk.sqlCreateString(dialect, mapping) );
// }
// }
}
}
@ -1546,7 +1535,6 @@ public class Configuration implements Serializable {
private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames) {
keyName = normalizer.normalizeIdentifierQuoting( keyName );
UniqueKey uc;
int size = columnNames.length;
Column[] columns = new Column[size];
Set<Column> unbound = new HashSet<Column>();
@ -1563,10 +1551,10 @@ public class Configuration implements Serializable {
unboundNoLogical.add( new Column( logicalColumnName ) );
}
}
UniqueKey uk = table.getOrCreateUniqueKey( keyName );
for ( Column column : columns ) {
if ( table.containsColumn( column ) ) {
uc = table.getOrCreateUniqueKey( keyName );
uc.addColumn( table.getColumn( column ) );
uk.addColumn( column );
unbound.remove( column );
}
}

View File

@ -1403,6 +1403,12 @@ public final class HbmBinder {
if ( nodeName == null ) nodeName = node.attributeValue( "name" );
collection.setNodeName( nodeName );
String embed = node.attributeValue( "embed-xml" );
// sometimes embed is set to the default value when not specified in the mapping,
// so can't seem to determine if an attribute was explicitly set;
// log a warning if embed has a value different from the default.
if ( !StringHelper.isEmpty( embed ) && !"true".equals( embed ) ) {
LOG.embedXmlAttributesNoLongerSupported();
}
collection.setEmbedded( embed==null || "true".equals(embed) );
@ -1626,6 +1632,12 @@ public final class HbmBinder {
manyToOne.setReferencedEntityName( getEntityName( node, mappings ) );
String embed = node.attributeValue( "embed-xml" );
// sometimes embed is set to the default value when not specified in the mapping,
// so can't seem to determine if an attribute was explicitly set;
// log a warning if embed has a value different from the default.
if ( !StringHelper.isEmpty( embed ) && !"true".equals( embed ) ) {
LOG.embedXmlAttributesNoLongerSupported();
}
manyToOne.setEmbedded( embed == null || "true".equals( embed ) );
String notFound = node.attributeValue( "not-found" );
@ -1702,7 +1714,14 @@ public final class HbmBinder {
initOuterJoinFetchSetting( node, oneToOne );
initLaziness( node, oneToOne, mappings, true );
oneToOne.setEmbedded( "true".equals( node.attributeValue( "embed-xml" ) ) );
String embed = node.attributeValue( "embed-xml" );
// sometimes embed is set to the default value when not specified in the mapping,
// so can't seem to determine if an attribute was explicitly set;
// log a warning if embed has a value different from the default.
if ( !StringHelper.isEmpty( embed ) && !"true".equals( embed ) ) {
LOG.embedXmlAttributesNoLongerSupported();
}
oneToOne.setEmbedded( "true".equals( embed ) );
Attribute fkNode = node.attribute( "foreign-key" );
if ( fkNode != null ) oneToOne.setForeignKeyName( fkNode.getValue() );
@ -1730,6 +1749,12 @@ public final class HbmBinder {
oneToMany.setReferencedEntityName( getEntityName( node, mappings ) );
String embed = node.attributeValue( "embed-xml" );
// sometimes embed is set to the default value when not specified in the mapping,
// so can't seem to determine if an attribute was explicitly set;
// log a warning if embed has a value different from the default.
if ( !StringHelper.isEmpty( embed ) && !"true".equals( embed ) ) {
LOG.embedXmlAttributesNoLongerSupported();
}
oneToMany.setEmbedded( embed == null || "true".equals( embed ) );
String notFound = node.attributeValue( "not-found" );

View File

@ -89,6 +89,7 @@ public final class Settings {
private MultiTableBulkIdStrategy multiTableBulkIdStrategy;
private BatchFetchStyle batchFetchStyle;
private boolean directReferenceCacheEntriesEnabled;
/**
@ -223,6 +224,10 @@ public final class Settings {
return structuredCacheEntriesEnabled;
}
public boolean isDirectReferenceCacheEntriesEnabled() {
return directReferenceCacheEntriesEnabled;
}
public EntityMode getDefaultEntityMode() {
return defaultEntityMode;
}
@ -442,4 +447,8 @@ public final class Settings {
void setBatchFetchStyle(BatchFetchStyle batchFetchStyle) {
this.batchFetchStyle = batchFetchStyle;
}
public void setDirectReferenceCacheEntriesEnabled(boolean directReferenceCacheEntriesEnabled) {
this.directReferenceCacheEntriesEnabled = directReferenceCacheEntriesEnabled;
}
}

View File

@ -295,6 +295,16 @@ public class SettingsFactory implements Serializable {
}
settings.setStructuredCacheEntriesEnabled( useStructuredCacheEntries );
boolean useDirectReferenceCacheEntries = ConfigurationHelper.getBoolean(
AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES,
properties,
false
);
if ( debugEnabled ) {
LOG.debugf( "Second-level cache direct-reference entries: %s", enabledDisabled(useDirectReferenceCacheEntries) );
}
settings.setDirectReferenceCacheEntriesEnabled( useDirectReferenceCacheEntries );
boolean useIdentifierRollback = ConfigurationHelper.getBoolean( AvailableSettings.USE_IDENTIFIER_ROLLBACK, properties );
if ( debugEnabled ) {
LOG.debugf( "Deleted entity synthetic identifier rollback: %s", enabledDisabled(useIdentifierRollback) );

View File

@ -184,7 +184,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
isTempSession = true;
}
else {
throw new LazyInitializationException( "could not initialize proxy - no Session" );
throwLazyInitializationException( "could not initialize proxy - no Session" );
}
}
else if ( !session.isOpen() ) {
@ -194,7 +194,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
isTempSession = true;
}
else {
throw new LazyInitializationException( "could not initialize proxy - the owning Session was closed" );
throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
}
}
else if ( !session.isConnected() ) {
@ -204,7 +204,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
isTempSession = true;
}
else {
throw new LazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
}
}

View File

@ -401,11 +401,6 @@ public class Cache71Dialect extends Dialect {
return false;
}
public boolean supportsUnique() {
// Does this dialect support the UNIQUE column syntax?
return true;
}
/**
* The syntax used to add a foreign key constraint to a table.
*

View File

@ -30,12 +30,13 @@ import java.sql.Types;
import org.hibernate.JDBCException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.AnsiTrimEmulationFunction;
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.dialect.unique.DB2UniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper;
@ -49,6 +50,8 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
* @author Gavin King
*/
public class DB2Dialect extends Dialect {
private final UniqueDelegate uniqueDelegate;
public DB2Dialect() {
super();
@ -175,6 +178,8 @@ public class DB2Dialect extends Dialect {
registerKeyword( "only" );
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
uniqueDelegate = new DB2UniqueDelegate( this );
}
@Override
public String getLowercaseFunction() {
@ -279,10 +284,6 @@ public class DB2Dialect extends Dialect {
return false;
}
@Override
public boolean supportsNotNullUnique() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
@ -456,5 +457,10 @@ public class DB2Dialect extends Dialect {
}
};
}
@Override
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
}

View File

@ -58,6 +58,8 @@ import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
import org.hibernate.dialect.lock.SelectLockingStrategy;
import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SessionImplementor;
@ -128,6 +130,8 @@ public abstract class Dialect implements ConversionContext {
private final Properties properties = new Properties();
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
private final Set<String> sqlKeywords = new HashSet<String>();
private final UniqueDelegate uniqueDelegate;
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -216,6 +220,8 @@ public abstract class Dialect implements ConversionContext {
registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() );
registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() );
registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() );
uniqueDelegate = new DefaultUniqueDelegate( this );
}
/**
@ -1951,23 +1957,6 @@ public abstract class Dialect implements ConversionContext {
return true;
}
/**
* Does this dialect support the <tt>UNIQUE</tt> column syntax?
*
* @return boolean
*/
public boolean supportsUnique() {
return true;
}
/**
* Does this dialect support adding Unique constraints via create and alter table ?
* @return boolean
*/
public boolean supportsUniqueConstraintInCreateAlterTable() {
return true;
}
/**
* The syntax used to add a column to a table (optional).
*
@ -2033,16 +2022,6 @@ public abstract class Dialect implements ConversionContext {
return " add constraint " + constraintName + " primary key ";
}
/**
* The syntax used to add a unique constraint to a table.
*
* @param constraintName The name of the unique constraint.
* @return The "add unique" fragment
*/
public String getAddUniqueConstraintString(String constraintName) {
return " add constraint " + constraintName + " unique ";
}
public boolean hasSelfReferentialForeignKeyBug() {
return false;
}
@ -2100,10 +2079,6 @@ public abstract class Dialect implements ConversionContext {
return true;
}
public boolean supportsNotNullUnique() {
return true;
}
/**
* Completely optional cascading drop clause
*
@ -2443,4 +2418,20 @@ public abstract class Dialect implements ConversionContext {
public boolean forceLobAsLastValue() {
return false;
}
/**
* Some dialects have trouble applying pessimistic locking depending upon what other query options are
* specified (paging, ordering, etc). This method allows these dialects to request that locking be applied
* by subsequent selects.
*
* @return {@code true} indicates that the dialect requests that locking be applied by subsequent select;
* {@code false} (the default) indicates that locking should be applied to the main SQL statement..
*/
public boolean useFollowOnLocking() {
return false;
}
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
}

View File

@ -217,10 +217,6 @@ public class H2Dialect extends Dialect {
return " for update";
}
public boolean supportsUnique() {
return true;
}
public boolean supportsLimit() {
return true;
}

View File

@ -251,10 +251,6 @@ public class HSQLDialect extends Dialect {
}
}
public boolean supportsUnique() {
return false;
}
public boolean supportsLimit() {
return true;
}

View File

@ -306,13 +306,6 @@ public class IngresDialect extends Dialect {
return true;
}
/**
* Ingres explicitly needs "unique not null", because "with null" is default
*/
public boolean supportsNotNullUnique() {
return false;
}
/**
* Does this dialect support temporary tables?
*/

View File

@ -577,4 +577,8 @@ public class Oracle8iDialect extends Dialect {
return true;
}
@Override
public boolean useFollowOnLocking() {
return true;
}
}

View File

@ -240,13 +240,6 @@ public class RDMSOS2200Dialect extends Dialect {
return ""; // Original Dialect.java returns " for update";
}
/**
* RDMS does not support adding Unique constraints via create and alter table.
*/
public boolean supportsUniqueConstraintInCreateAlterTable() {
return true;
}
// Verify the state of this new method in Hibernate 3.0 Dialect.java
/**
* RDMS does not support Cascade Deletes.

View File

@ -422,10 +422,6 @@ public class SybaseASE15Dialect extends SybaseDialect {
return false;
}
public boolean supportsUniqueConstraintInCreateAlterTable() {
return false;
}
public String getCrossJoinSeparator() {
return ", ";
}

View File

@ -102,14 +102,6 @@ public class TimesTenDialect extends Dialect {
public boolean qualifyIndexName() {
return false;
}
public boolean supportsUnique() {
return false;
}
public boolean supportsUniqueConstraintInCreateAlterTable() {
return false;
}
public String getAddColumnString() {
return "add";

View File

@ -0,0 +1,109 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.dialect.unique;
import java.util.Iterator;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.Index;
import org.hibernate.metamodel.relational.UniqueKey;
/**
* DB2 does not allow unique constraints on nullable columns. Rather than
* forcing "not null", use unique *indexes* instead.
*
* @author Brett Meyer
*/
public class DB2UniqueDelegate extends DefaultUniqueDelegate {
public DB2UniqueDelegate( Dialect dialect ) {
super( dialect );
}
@Override
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema ) {
if ( hasNullable( uniqueKey ) ) {
return org.hibernate.mapping.Index.buildSqlCreateIndexString(
dialect, uniqueKey.getName(), uniqueKey.getTable(),
uniqueKey.columnIterator(), true, defaultCatalog,
defaultSchema );
} else {
return super.applyUniquesOnAlter(
uniqueKey, defaultCatalog, defaultSchema );
}
}
@Override
public String applyUniquesOnAlter( UniqueKey uniqueKey ) {
if ( hasNullable( uniqueKey ) ) {
return Index.buildSqlCreateIndexString(
dialect, uniqueKey.getName(), uniqueKey.getTable(),
uniqueKey.getColumns(), true );
} else {
return super.applyUniquesOnAlter( uniqueKey );
}
}
@Override
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema ) {
if ( hasNullable( uniqueKey ) ) {
return org.hibernate.mapping.Index.buildSqlDropIndexString(
dialect, uniqueKey.getTable(), uniqueKey.getName(),
defaultCatalog, defaultSchema );
} else {
return super.dropUniquesOnAlter(
uniqueKey, defaultCatalog, defaultSchema );
}
}
@Override
public String dropUniquesOnAlter( UniqueKey uniqueKey ) {
if ( hasNullable( uniqueKey ) ) {
return Index.buildSqlDropIndexString(
dialect, uniqueKey.getTable(), uniqueKey.getName() );
} else {
return super.dropUniquesOnAlter( uniqueKey );
}
}
private boolean hasNullable( org.hibernate.mapping.UniqueKey uniqueKey ) {
Iterator iter = uniqueKey.getColumnIterator();
while ( iter.hasNext() ) {
if ( ( ( org.hibernate.mapping.Column ) iter.next() ).isNullable() ) {
return true;
}
}
return false;
}
private boolean hasNullable( UniqueKey uniqueKey ) {
Iterator iter = uniqueKey.getColumns().iterator();
while ( iter.hasNext() ) {
if ( ( ( Column ) iter.next() ).isNullable() ) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,148 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.dialect.unique;
import java.util.Iterator;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.Table;
import org.hibernate.metamodel.relational.UniqueKey;
/**
* The default UniqueDelegate implementation for most dialects. Uses
* separate create/alter statements to apply uniqueness to a column.
*
* @author Brett Meyer
*/
public class DefaultUniqueDelegate implements UniqueDelegate {
protected final Dialect dialect;
public DefaultUniqueDelegate( Dialect dialect ) {
this.dialect = dialect;
}
@Override
public String applyUniqueToColumn( org.hibernate.mapping.Column column ) {
return "";
}
@Override
public String applyUniqueToColumn( Column column ) {
return "";
}
@Override
public String applyUniquesToTable( org.hibernate.mapping.Table table ) {
return "";
}
@Override
public String applyUniquesToTable( Table table ) {
return "";
}
@Override
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema ) {
// Do this here, rather than allowing UniqueKey/Constraint to do it.
// We need full, simplified control over whether or not it happens.
return new StringBuilder( "alter table " )
.append( uniqueKey.getTable().getQualifiedName(
dialect, defaultCatalog, defaultSchema ) )
.append( " add constraint " )
.append( uniqueKey.getName() )
.append( uniqueConstraintSql( uniqueKey ) )
.toString();
}
@Override
public String applyUniquesOnAlter( UniqueKey uniqueKey ) {
// Do this here, rather than allowing UniqueKey/Constraint to do it.
// We need full, simplified control over whether or not it happens.
return new StringBuilder( "alter table " )
.append( uniqueKey.getTable().getQualifiedName( dialect ) )
.append( " add constraint " )
.append( uniqueKey.getName() )
.append( uniqueConstraintSql( uniqueKey ) )
.toString();
}
@Override
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema ) {
// Do this here, rather than allowing UniqueKey/Constraint to do it.
// We need full, simplified control over whether or not it happens.
return new StringBuilder( "alter table " )
.append( uniqueKey.getTable().getQualifiedName(
dialect, defaultCatalog, defaultSchema ) )
.append( " drop constraint " )
.append( dialect.quote( uniqueKey.getName() ) )
.toString();
}
@Override
public String dropUniquesOnAlter( UniqueKey uniqueKey ) {
// Do this here, rather than allowing UniqueKey/Constraint to do it.
// We need full, simplified control over whether or not it happens.
return new StringBuilder( "alter table " )
.append( uniqueKey.getTable().getQualifiedName( dialect ) )
.append( " drop constraint " )
.append( dialect.quote( uniqueKey.getName() ) )
.toString();
}
@Override
public String uniqueConstraintSql( org.hibernate.mapping.UniqueKey uniqueKey ) {
StringBuilder sb = new StringBuilder();
sb.append( " unique (" );
Iterator columnIterator = uniqueKey.getColumnIterator();
while ( columnIterator.hasNext() ) {
org.hibernate.mapping.Column column
= (org.hibernate.mapping.Column) columnIterator.next();
sb.append( column.getQuotedName( dialect ) );
if ( columnIterator.hasNext() ) {
sb.append( ", " );
}
}
return sb.append( ')' ).toString();
}
@Override
public String uniqueConstraintSql( UniqueKey uniqueKey ) {
StringBuilder sb = new StringBuilder();
sb.append( " unique (" );
Iterator columnIterator = uniqueKey.getColumns().iterator();
while ( columnIterator.hasNext() ) {
org.hibernate.mapping.Column column
= (org.hibernate.mapping.Column) columnIterator.next();
sb.append( column.getQuotedName( dialect ) );
if ( columnIterator.hasNext() ) {
sb.append( ", " );
}
}
return sb.append( ')' ).toString();
}
}

View File

@ -0,0 +1,146 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.dialect.unique;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.Table;
import org.hibernate.metamodel.relational.UniqueKey;
/**
* Dialect-level delegate in charge of applying "uniqueness" to a column.
* Uniqueness can be defined in 1 of 3 ways:
*
* 1.) Add a unique constraint via separate alter table statements.
* 2.) Add a unique constraint via dialect-specific syntax in table create statement.
* 3.) Add "unique" syntax to the column itself.
*
* #1 & #2 are preferred, if possible -- #3 should be solely a fall-back.
*
* TODO: This could eventually be simplified. With AST, 1 "applyUniqueness"
* method might be possible. But due to .cfg and .mapping still resolving
* around StringBuilders, separate methods were needed.
*
* See HHH-7797.
*
* @author Brett Meyer
*/
public interface UniqueDelegate {
/**
* If the dialect does not supports unique constraints, this method should
* return the syntax necessary to mutate the column definition
* (usually "unique").
*
* @param column
* @return String
*/
public String applyUniqueToColumn( org.hibernate.mapping.Column column );
/**
* If the dialect does not supports unique constraints, this method should
* return the syntax necessary to mutate the column definition
* (usually "unique").
*
* @param column
* @return String
*/
public String applyUniqueToColumn( Column column );
/**
* If constraints are supported, but not in seperate alter statements,
* return uniqueConstraintSql in order to add the constraint to the
* original table definition.
*
* @param table
* @return String
*/
public String applyUniquesToTable( org.hibernate.mapping.Table table );
/**
* If constraints are supported, but not in seperate alter statements,
* return uniqueConstraintSql in order to add the constraint to the
* original table definition.
*
* @param table
* @return String
*/
public String applyUniquesToTable( Table table );
/**
* If creating unique constraints in separate alter statements is
* supported, generate the necessary "alter" syntax for the given key.
*
* @param uniqueKey
* @param defaultCatalog
* @param defaultSchema
* @return String
*/
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema );
/**
* If creating unique constraints in separate alter statements is
* supported, generate the necessary "alter" syntax for the given key.
*
* @param uniqueKey
* @return String
*/
public String applyUniquesOnAlter( UniqueKey uniqueKey );
/**
* If dropping unique constraints in separate alter statements is
* supported, generate the necessary "alter" syntax for the given key.
*
* @param uniqueKey
* @param defaultCatalog
* @param defaultSchema
* @return String
*/
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
String defaultCatalog, String defaultSchema );
/**
* If dropping unique constraints in separate alter statements is
* supported, generate the necessary "alter" syntax for the given key.
*
* @param uniqueKey
* @return String
*/
public String dropUniquesOnAlter( UniqueKey uniqueKey );
/**
* Generates the syntax necessary to create the unique constraint (reused
* by all methods). Ex: "unique (column1, column2, ...)"
*
* @param uniqueKey
* @return String
*/
public String uniqueConstraintSql( org.hibernate.mapping.UniqueKey uniqueKey );
/**
* Generates the syntax necessary to create the unique constraint (reused
* by all methods). Ex: "unique (column1, column2, ...)"
*
* @param uniqueKey
* @return String
*/
public String uniqueConstraintSql( UniqueKey uniqueKey );
}

View File

@ -197,14 +197,7 @@ public final class TwoPhaseLoad {
}
Object version = Versioning.getVersion(hydratedState, persister);
CacheEntry entry = new CacheEntry(
hydratedState,
persister,
entityEntry.isLoadedWithLazyPropertiesUnfetched(),
version,
session,
entity
);
CacheEntry entry = persister.buildCacheEntry( entity, hydratedState, version, session );
CacheKey cacheKey = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
// explicit handling of caching for rows just inserted and then somehow forced to be read

View File

@ -35,6 +35,8 @@ import org.hibernate.TypeMismatchException;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry;
@ -529,52 +531,172 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
final LoadEventListener.LoadType options) {
final SessionImplementor source = event.getSession();
final boolean useCache = persister.hasCache()
&& source.getCacheMode().isGetEnabled()
&& event.getLockMode().lessThan(LockMode.READ);
if ( useCache ) {
if ( ! useCache ) {
// we can't use cache here
return null;
}
final SessionFactoryImplementor factory = source.getFactory();
final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey(
event.getEntityId(),
persister.getIdentifierType(),
persister.getRootEntityName()
);
final CacheKey ck = source.generateCacheKey(
event.getEntityId(),
persister.getIdentifierType(),
persister.getRootEntityName()
);
Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
if ( factory.getStatistics().isStatisticsEnabled() ) {
if ( ce == null ) {
factory.getStatisticsImplementor().secondLevelCacheMiss(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
else {
factory.getStatisticsImplementor().secondLevelCacheHit(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
if ( factory.getStatistics().isStatisticsEnabled() ) {
if ( ce == null ) {
factory.getStatisticsImplementor().secondLevelCacheMiss(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
if ( ce != null ) {
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
// Entity was found in second-level cache...
return assembleCacheEntry(
entry,
event.getEntityId(),
persister,
event
else {
factory.getStatisticsImplementor().secondLevelCacheHit(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
}
return null;
if ( ce == null ) {
// nothing was found in cache
return null;
}
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
return convertCacheEntryToEntity( entry, event.getEntityId(), persister, event );
}
private Object convertCacheEntryToEntity(
CacheEntry entry,
Serializable entityId,
EntityPersister persister,
LoadEvent event) {
final EventSource session = event.getSession();
final SessionFactoryImplementor factory = session.getFactory();
final EntityPersister subclassPersister = factory.getEntityPersister( entry.getSubclass() );
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
"Converting second-level cache entry [%s] into entity : %s",
entry,
MessageHelper.infoString( persister, entityId, factory )
);
}
final Object entity;
if ( entry.isReferenceEntry() ) {
final Object optionalObject = event.getInstanceToLoad();
if ( optionalObject != null ) {
throw new HibernateException(
String.format(
"Attempt to load entity [%s] from cache using provided object instance, but cache " +
"is storing references",
MessageHelper.infoString( persister, entityId, factory )
)
);
}
entity = ( (ReferenceCacheEntryImpl) entry ).getReference();
if ( entity == null ) {
throw new IllegalStateException(
"Reference cache entry contained null : " + MessageHelper.infoString( persister, entityId, factory )
);
}
}
else {
final Object optionalObject = event.getInstanceToLoad();
entity = optionalObject == null
? session.instantiate( subclassPersister, entityId )
: optionalObject;
}
// make it circular-reference safe
final EntityKey entityKey = session.generateEntityKey( entityId, subclassPersister );
TwoPhaseLoad.addUninitializedCachedEntity(
entityKey,
entity,
subclassPersister,
LockMode.NONE,
entry.areLazyPropertiesUnfetched(),
entry.getVersion(),
session
);
final PersistenceContext persistenceContext = session.getPersistenceContext();
final Object[] values;
final Object version;
final boolean isReadOnly;
if ( entry.isReferenceEntry() ) {
values = null;
version = null;
isReadOnly = true;
}
else {
final Type[] types = subclassPersister.getPropertyTypes();
// initializes the entity by (desired) side-effect
values = ( (StandardCacheEntryImpl) entry).assemble(
entity, entityId, subclassPersister, session.getInterceptor(), session
);
if ( ( (StandardCacheEntryImpl) entry ).isDeepCopyNeeded() ) {
TypeHelper.deepCopy(
values,
types,
subclassPersister.getPropertyUpdateability(),
values,
session
);
}
version = Versioning.getVersion( values, subclassPersister );
LOG.tracef( "Cached Version : %s", version );
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
// there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only
isReadOnly = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().isReadOnly();
}
else {
isReadOnly = session.isDefaultReadOnly();
}
}
persistenceContext.addEntry(
entity,
( isReadOnly ? Status.READ_ONLY : Status.MANAGED ),
values,
null,
entityId,
version,
LockMode.NONE,
true,
subclassPersister,
false,
entry.areLazyPropertiesUnfetched()
);
subclassPersister.afterInitialize( entity, entry.areLazyPropertiesUnfetched(), session );
persistenceContext.initializeNonLazyCollections();
//PostLoad is needed for EJB3
PostLoadEvent postLoadEvent = new PostLoadEvent( session )
.setEntity( entity )
.setId( entityId )
.setPersister( persister );
for ( PostLoadEventListener listener : postLoadEventListeners( session ) ) {
listener.onPostLoad( postLoadEvent );
}
return entity;
}
private Object assembleCacheEntry(
final CacheEntry entry,
final StandardCacheEntryImpl entry,
final Serializable id,
final EntityPersister persister,
final LoadEvent event) throws HibernateException {
@ -642,7 +764,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
subclassPersister,
false,
entry.areLazyPropertiesUnfetched()
);
);
subclassPersister.afterInitialize( result, entry.areLazyPropertiesUnfetched(), session );
persistenceContext.initializeNonLazyCollections();
// upgrade the lock if necessary:

View File

@ -174,11 +174,12 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
}
setText( joinedFragment );
}
return true;
}
else {
else if ( columnExpressions.length > 0 ) {
setText( columnExpressions[0] );
return true;
}
return true;
}
return false;
}

View File

@ -953,7 +953,8 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator
if ( stats ) startTime = System.currentTimeMillis();
try {
final ResultSet rs = executeQueryStatement( queryParameters, false, session );
final List<AfterLoadAction> afterLoadActions = new ArrayList<AfterLoadAction>();
final ResultSet rs = executeQueryStatement( queryParameters, false, afterLoadActions, session );
final PreparedStatement st = (PreparedStatement) rs.getStatement();
HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(holderConstructor, queryParameters.getResultTransformer());
Iterator result = new IteratorImpl( rs, st, session, queryParameters.isReadOnly( session ), returnTypes, getColumnNames(), hi );
@ -1094,8 +1095,13 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator
}
@Override
protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws QueryException {
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws QueryException {
// can't cache this stuff either (per-invocation)
final LockOptions lockOptions = parameters.getLockOptions();
final String result;
if ( lockOptions == null ||
( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {

View File

@ -104,7 +104,7 @@ public class TemporaryTableBulkIdStrategy implements MultiTableBulkIdStrategy {
session.getTransactionCoordinator()
.getTransaction()
.createIsolationDelegate()
.delegateWork( work, session.getFactory().getSettings().isDataDefinitionInTransactionSupported() );
.delegateWork( work, shouldTransactIsolatedTemporaryTableDDL( session ) );
}
else {
final Connection connection = session.getTransactionCoordinator()
@ -126,7 +126,7 @@ public class TemporaryTableBulkIdStrategy implements MultiTableBulkIdStrategy {
session.getTransactionCoordinator()
.getTransaction()
.createIsolationDelegate()
.delegateWork( work, session.getFactory().getSettings().isDataDefinitionInTransactionSupported() );
.delegateWork( work, shouldTransactIsolatedTemporaryTableDDL( session ) );
}
else {
final Connection connection = session.getTransactionCoordinator()
@ -173,6 +173,13 @@ public class TemporaryTableBulkIdStrategy implements MultiTableBulkIdStrategy {
return session.getFactory().getSettings().isDataDefinitionImplicitCommit();
}
@SuppressWarnings({ "UnnecessaryUnboxing" })
protected boolean shouldTransactIsolatedTemporaryTableDDL(SessionImplementor session) {
// is there ever a time when it makes sense to do this?
// return session.getFactory().getSettings().isDataDefinitionInTransactionSupported();
return false;
}
private static class TemporaryTableCreationWork extends AbstractWork {
private final Queryable persister;

View File

@ -53,6 +53,7 @@ import org.hibernate.type.Type;
*
* @author Gavin King
* @author Steve Ebersole
* @author Brett Meyer
*/
public class IncrementGenerator implements IdentifierGenerator, Configurable {
@ -103,7 +104,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
for ( int i=0; i < tables.length; i++ ) {
final String tableName = dialect.quote( normalizer.normalizeIdentifierQuoting( tables[i] ) );
if ( tables.length > 1 ) {
buf.append( "select " ).append( column ).append( " from " );
buf.append( "select max(" ).append( column ).append( ") as mx from " );
}
buf.append( Table.qualify( catalog, schema, tableName ) );
if ( i < tables.length-1 ) {
@ -112,7 +113,7 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
}
if ( tables.length > 1 ) {
buf.insert( 0, "( " ).append( " ) ids_" );
column = "ids_." + column;
column = "ids_.mx";
}
sql = "select max(" + column + ") from " + buf.toString();

View File

@ -51,7 +51,6 @@ import org.hibernate.type.Type;
* Mapping parameters supported: sequence, parameters.
*
* @see SequenceHiLoGenerator
* @see TableHiLoGenerator
* @author Gavin King
*
* @deprecated Going away in 5.0, use {@link org.hibernate.id.enhanced.SequenceStyleGenerator} instead

View File

@ -40,12 +40,8 @@ import org.hibernate.type.Type;
* oracle-style sequence that generates hi values. The user may specify a
* maximum lo value to determine how often new hi values are fetched.<br>
* <br>
* If sequences are not available, <tt>TableHiLoGenerator</tt> might be an
* alternative.<br>
* <br>
* Mapping parameters supported: sequence, max_lo, parameters.
*
* @see TableHiLoGenerator
* @author Gavin King
*/
public class SequenceHiLoGenerator extends SequenceGenerator {

View File

@ -41,6 +41,7 @@ import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jdbc.AbstractReturningWork;

View File

@ -29,6 +29,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.enhanced.AccessCallback;
import org.hibernate.id.enhanced.OptimizerFactory;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.type.Type;
@ -47,7 +48,10 @@ import org.hibernate.type.Type;
*
* @see SequenceHiLoGenerator
* @author Gavin King
*
* @deprecate use {@link SequenceStyleGenerator} instead.
*/
@Deprecated
public class TableHiLoGenerator extends TableGenerator {
/**
* The max_lo parameter

View File

@ -45,6 +45,7 @@ import org.jboss.logging.Message;
import org.jboss.logging.MessageLogger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.cache.CacheException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.loading.internal.CollectionLoadContext;
@ -1625,4 +1626,28 @@ public interface CoreMessageLogger extends BasicLogger {
"@Access has to be placed on the field with an access type of AccessType.FIELD. " +
"Using AccessType.PROPERTY on the field has no effect", id = 453)
String accessTypeOverrideShouldBeField( String className );
@LogMessage(level = WARN)
@Message(
value = "Encountered request for locking however dialect reports that database prefers locking be done in a " +
"separate select (follow-on locking); results will be locked after initial query executes",
id = 444
)
void usingFollowOnLocking();
@LogMessage(level = WARN)
@Message(
value = "Alias-specific lock modes requested, which is not currently supported with follow-on locking; " +
"all acquired locks will be [%s]",
id = 445
)
void aliasSpecificLockingWithFollowOnLocking(LockMode lockMode);
@LogMessage(level = WARN)
@Message(
value = "embed-xml attributes were intended to be used for DOM4J entity mode. Since that entity mode has been " +
"removed, embed-xml attributes are no longer supported and should be removed from mappings.",
id = 446
)
void embedXmlAttributesNoLongerSupported();
}

View File

@ -69,6 +69,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
private Collection<String> querySpaces;
private final boolean callable;
private final LockOptions lockOptions = new LockOptions();
/**
* Constructs a SQLQueryImpl given a sql query defined in the mappings.
@ -244,8 +245,8 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
@Override
public LockOptions getLockOptions() {
//we never need to apply locks to the SQL
return null;
//we never need to apply locks to the SQL, however the native-sql loader handles this specially
return lockOptions;
}
@Override
public SQLQuery addScalar(final String columnAlias, final Type type) {

View File

@ -380,6 +380,8 @@ public final class SessionFactoryImpl
final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + ".";
final PersisterFactory persisterFactory = serviceRegistry.getService( PersisterFactory.class );
entityPersisters = new HashMap();
Map entityAccessStrategies = new HashMap();
Map<String,ClassMetadata> classMeta = new HashMap<String,ClassMetadata>();
@ -431,7 +433,7 @@ public final class SessionFactoryImpl
}
}
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
EntityPersister cp = persisterFactory.createEntityPersister(
model,
accessStrategy,
naturalIdAccessStrategy,
@ -460,7 +462,7 @@ public final class SessionFactoryImpl
entityAccessStrategies.put( cacheRegionName, accessStrategy );
cacheAccess.addCacheRegion( cacheRegionName, collectionRegion );
}
CollectionPersister persister = serviceRegistry.getService( PersisterFactory.class ).createCollectionPersister(
CollectionPersister persister = persisterFactory.createCollectionPersister(
model,
accessStrategy,
this

View File

@ -26,6 +26,7 @@ package org.hibernate.internal;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -299,6 +300,8 @@ public class StoredProcedureOutputsImpl implements StoredProcedureOutputs {
this.session = session;
}
// todo : this would be a great way to add locking to stored procedure support (at least where returning entities).
public List processResultSet(ResultSet resultSet) throws SQLException {
super.autoDiscoverTypes( resultSet );
return super.processResultSet(
@ -307,7 +310,8 @@ public class StoredProcedureOutputsImpl implements StoredProcedureOutputs {
session,
true,
null,
Integer.MAX_VALUE
Integer.MAX_VALUE,
Collections.<AfterLoadAction>emptyList()
);
}
}

View File

@ -31,6 +31,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -47,6 +48,7 @@ import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.WrongClassException;
import org.hibernate.cache.spi.FilterKey;
@ -59,6 +61,7 @@ import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.dialect.pagination.NoopLimitHandler;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.jdbc.ColumnNameCache;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.EntityUniqueKey;
import org.hibernate.engine.spi.PersistenceContext;
@ -195,7 +198,11 @@ public abstract class Loader {
* empty superclass implementation merely returns its first
* argument.
*/
protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws HibernateException {
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws HibernateException {
return sql;
}
@ -227,13 +234,54 @@ public abstract class Loader {
/**
* Modify the SQL, adding lock hints and comments, if necessary
*/
protected String preprocessSQL(String sql, QueryParameters parameters, Dialect dialect)
throws HibernateException {
protected String preprocessSQL(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws HibernateException {
sql = applyLocks( sql, parameters, dialect, afterLoadActions );
return getFactory().getSettings().isCommentsEnabled()
? prependComment( sql, parameters )
: sql;
}
sql = applyLocks( sql, parameters.getLockOptions(), dialect );
protected static interface AfterLoadAction {
public void afterLoad(SessionImplementor session, Object entity, Loadable persister);
}
return getFactory().getSettings().isCommentsEnabled() ?
prependComment( sql, parameters ) : sql;
protected boolean shouldUseFollowOnLocking(
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) {
if ( dialect.useFollowOnLocking() ) {
LOG.usingFollowOnLocking();
// currently only one lock mode is allowed in follow-on locking
final LockMode lockMode = determineFollowOnLockMode( parameters.getLockOptions() );
final LockOptions lockOptions = new LockOptions( lockMode );
lockOptions.setTimeOut( parameters.getLockOptions().getTimeOut() );
lockOptions.setScope( parameters.getLockOptions().getScope() );
afterLoadActions.add(
new AfterLoadAction() {
@Override
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
( (Session) session ).buildLockRequest( lockOptions ).lock( persister.getEntityName(), entity );
}
}
);
parameters.setLockOptions( new LockOptions() );
return true;
}
return false;
}
protected LockMode determineFollowOnLockMode(LockOptions lockOptions) {
final LockMode lockModeToUse = lockOptions.findGreatestLockMode();
if ( lockOptions.hasAliasSpecificLockModes() ) {
LOG.aliasSpecificLockingWithFollowOnLocking( lockModeToUse );
}
return lockModeToUse;
}
private String prependComment(String sql, QueryParameters parameters) {
@ -351,7 +399,7 @@ public abstract class Loader {
resultSet,
session,
queryParameters.isReadOnly( session )
);
);
session.getPersistenceContext().initializeNonLazyCollections();
return result;
}
@ -410,7 +458,7 @@ public abstract class Loader {
resultSet,
session,
queryParameters.isReadOnly( session )
);
);
session.getPersistenceContext().initializeNonLazyCollections();
return result;
}
@ -843,7 +891,9 @@ public abstract class Loader {
selection.getMaxRows() :
Integer.MAX_VALUE;
final ResultSet rs = executeQueryStatement( queryParameters, false, session );
final List<AfterLoadAction> afterLoadActions = new ArrayList<AfterLoadAction>();
final ResultSet rs = executeQueryStatement( queryParameters, false, afterLoadActions, session );
final Statement st = rs.getStatement();
// would be great to move all this below here into another method that could also be used
@ -853,7 +903,7 @@ public abstract class Loader {
// that I could do the control breaking at the means to know when to stop
try {
return processResultSet( rs, queryParameters, session, returnProxies, forcedResultTransformer, maxRows );
return processResultSet( rs, queryParameters, session, returnProxies, forcedResultTransformer, maxRows, afterLoadActions );
}
finally {
st.close();
@ -867,7 +917,8 @@ public abstract class Loader {
SessionImplementor session,
boolean returnProxies,
ResultTransformer forcedResultTransformer,
int maxRows) throws SQLException {
int maxRows,
List<AfterLoadAction> afterLoadActions) throws SQLException {
final int entitySpan = getEntityPersisters().length;
final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
final LockMode[] lockModesArray = getLockModes( queryParameters.getLockOptions() );
@ -902,8 +953,16 @@ public abstract class Loader {
LOG.tracev( "Done processing result set ({0} rows)", count );
initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly( session ) );
if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session );
initializeEntitiesAndCollections(
hydratedObjects,
rs,
session,
queryParameters.isReadOnly( session ),
afterLoadActions
);
if ( createSubselects ) {
createSubselects( subselectResultKeys, queryParameters, session );
}
return results;
}
@ -989,8 +1048,22 @@ public abstract class Loader {
final List hydratedObjects,
final Object resultSetId,
final SessionImplementor session,
final boolean readOnly)
throws HibernateException {
final boolean readOnly) throws HibernateException {
initializeEntitiesAndCollections(
hydratedObjects,
resultSetId,
session,
readOnly,
Collections.<AfterLoadAction>emptyList()
);
}
private void initializeEntitiesAndCollections(
final List hydratedObjects,
final Object resultSetId,
final SessionImplementor session,
final boolean readOnly,
List<AfterLoadAction> afterLoadActions) throws HibernateException {
final CollectionPersister[] collectionPersisters = getCollectionPersisters();
if ( collectionPersisters != null ) {
@ -1042,9 +1115,19 @@ public abstract class Loader {
// split off from initializeEntity. It *must* occur after
// endCollectionLoad to ensure the collection is in the
// persistence context.
if ( hydratedObjects!=null ) {
if ( hydratedObjects != null ) {
for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.postLoad( hydratedObject, session, post );
if ( afterLoadActions != null ) {
for ( AfterLoadAction afterLoadAction : afterLoadActions ) {
final EntityEntry entityEntry = session.getPersistenceContext().getEntry( hydratedObject );
if ( entityEntry == null ) {
// big problem
throw new HibernateException( "Could not locate EntityEntry immediately after two-phase load" );
}
afterLoadAction.afterLoad( session, hydratedObject, (Loadable) entityEntry.getPersister() );
}
}
}
}
}
@ -1721,15 +1804,17 @@ public abstract class Loader {
protected ResultSet executeQueryStatement(
final QueryParameters queryParameters,
final boolean scroll,
List<AfterLoadAction> afterLoadActions,
final SessionImplementor session) throws SQLException {
return executeQueryStatement( getSQLString(), queryParameters, scroll, session );
return executeQueryStatement( getSQLString(), queryParameters, scroll, afterLoadActions, session );
}
protected ResultSet executeQueryStatement(
final String sqlStatement,
final QueryParameters queryParameters,
final boolean scroll,
final SessionImplementor session) throws SQLException {
String sqlStatement,
QueryParameters queryParameters,
boolean scroll,
List<AfterLoadAction> afterLoadActions,
SessionImplementor session) throws SQLException {
// Processing query filters.
queryParameters.processFilters( sqlStatement, session );
@ -1742,7 +1827,7 @@ public abstract class Loader {
String sql = limitHandler.getProcessedSql();
// Adding locks and comments.
sql = preprocessSQL( sql, queryParameters, getFactory().getDialect() );
sql = preprocessSQL( sql, queryParameters, getFactory().getDialect(), afterLoadActions );
final PreparedStatement st = prepareQueryStatement( sql, queryParameters, limitHandler, scroll, session );
return getResultSet( st, queryParameters.getRowSelection(), limitHandler, queryParameters.hasAutoDiscoverScalarTypes(), session );
@ -2499,7 +2584,7 @@ public abstract class Loader {
if ( stats ) startTime = System.currentTimeMillis();
try {
final ResultSet rs = executeQueryStatement( queryParameters, true, session );
final ResultSet rs = executeQueryStatement( queryParameters, true, Collections.<AfterLoadAction>emptyList(), session );
final PreparedStatement st = (PreparedStatement) rs.getStatement();
if ( stats ) {

View File

@ -28,6 +28,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.dialect.pagination.LimitHelper;
@ -250,10 +252,11 @@ public class DynamicBatchingCollectionInitializerBuilder extends BatchingCollect
selection.getMaxRows() :
Integer.MAX_VALUE;
final ResultSet rs = executeQueryStatement( sql, queryParameters, false, session );
final List<AfterLoadAction> afterLoadActions = Collections.emptyList();
final ResultSet rs = executeQueryStatement( sql, queryParameters, false, afterLoadActions, session );
final Statement st = rs.getStatement();
try {
processResultSet( rs, queryParameters, session, true, null, maxRows );
processResultSet( rs, queryParameters, session, true, null, maxRows, afterLoadActions );
}
finally {
st.close();

View File

@ -36,6 +36,7 @@ import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.QueryParameters;
@ -44,6 +45,7 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.OuterJoinLoader;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.transform.ResultTransformer;
@ -190,10 +192,38 @@ public class CriteriaLoader extends OuterJoinLoader {
return querySpaces;
}
protected String applyLocks(String sqlSelectString, LockOptions lockOptions, Dialect dialect) throws QueryException {
@Override
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws QueryException {
final LockOptions lockOptions = parameters.getLockOptions();
if ( lockOptions == null ||
( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
return sqlSelectString;
return sql;
}
if ( dialect.useFollowOnLocking() ) {
// Dialect prefers to perform locking in a separate step
LOG.usingFollowOnLocking();
final LockMode lockMode = determineFollowOnLockMode( lockOptions );
final LockOptions lockOptionsToUse = new LockOptions( lockMode );
lockOptionsToUse.setTimeOut( lockOptions.getTimeOut() );
lockOptionsToUse.setScope( lockOptions.getScope() );
afterLoadActions.add(
new AfterLoadAction() {
@Override
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
( (Session) session ).buildLockRequest( lockOptionsToUse )
.lock( persister.getEntityName(), entity );
}
}
);
parameters.setLockOptions( new LockOptions() );
return sql;
}
final LockOptions locks = new LockOptions(lockOptions.getLockMode());
@ -213,7 +243,20 @@ public class CriteriaLoader extends OuterJoinLoader {
}
}
}
return dialect.applyLocksToSql( sqlSelectString, locks, keyColumnNames );
return dialect.applyLocksToSql( sql, locks, keyColumnNames );
}
protected LockMode determineFollowOnLockMode(LockOptions lockOptions) {
final LockMode lockModeToUse = lockOptions.findGreatestLockMode();
if ( lockOptions.getAliasLockCount() > 1 ) {
// > 1 here because criteria always uses alias map for the root lock mode (under 'this_')
LOG.aliasSpecificLockingWithFollowOnLocking( lockModeToUse );
}
return lockModeToUse;
}
protected LockMode[] getLockModes(LockOptions lockOptions) {

View File

@ -27,6 +27,7 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -37,7 +38,12 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.internal.HolderInstantiator;
@ -49,6 +55,7 @@ import org.hibernate.loader.Loader;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.CollectionType;
@ -314,6 +321,35 @@ public class CustomLoader extends Loader {
return list( session, queryParameters, querySpaces, resultTypes );
}
@Override
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws QueryException {
final LockOptions lockOptions = parameters.getLockOptions();
if ( lockOptions == null ||
( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
return sql;
}
// user is request locking, lets see if we can apply locking directly to the SQL...
// some dialects wont allow locking with paging...
afterLoadActions.add(
new AfterLoadAction() {
private final LockOptions originalLockOptions = lockOptions.makeCopy();
@Override
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
( (Session) session ).buildLockRequest( originalLockOptions ).lock( persister.getEntityName(), entity );
}
}
);
parameters.getLockOptions().setLockMode( LockMode.READ );
return sql;
}
public ScrollableResults scroll(
final QueryParameters queryParameters,
final SessionImplementor session) throws HibernateException {

View File

@ -27,6 +27,7 @@ import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.jboss.logging.Logger;
@ -253,10 +254,11 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
selection.getMaxRows() :
Integer.MAX_VALUE;
final ResultSet rs = executeQueryStatement( sql, queryParameters, false, session );
final List<AfterLoadAction> afterLoadActions = new ArrayList<AfterLoadAction>();
final ResultSet rs = executeQueryStatement( sql, queryParameters, false, afterLoadActions, session );
final Statement st = rs.getStatement();
try {
return processResultSet( rs, queryParameters, session, false, null, maxRows );
return processResultSet( rs, queryParameters, session, false, null, maxRows, afterLoadActions );
}
finally {
st.close();

View File

@ -27,6 +27,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -307,16 +308,35 @@ public class QueryLoader extends BasicLoader {
return lockModesArray;
}
protected String applyLocks(String sql, LockOptions lockOptions, Dialect dialect) throws QueryException {
@Override
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws QueryException {
// can't cache this stuff either (per-invocation)
// we are given a map of user-alias -> lock mode
// create a new map of sql-alias -> lock mode
final LockOptions lockOptions = parameters.getLockOptions();
if ( lockOptions == null ||
( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
return sql;
}
// user is request locking, lets see if we can apply locking directly to the SQL...
// some dialects wont allow locking with paging...
if ( shouldUseFollowOnLocking( parameters, dialect, afterLoadActions ) ) {
return sql;
}
// there are other conditions we might want to add here, such as checking the result types etc
// but those are better served after we have redone the SQL generation to use ASTs.
// we need both the set of locks and the columns to reference in locks
// as the ultimate output of this section...
final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
@ -490,7 +510,7 @@ public class QueryLoader extends BasicLoader {
if ( queryParameters.isCallable() ) {
throw new QueryException("iterate() not supported for callable statements");
}
final ResultSet rs = executeQueryStatement( queryParameters, false, session );
final ResultSet rs = executeQueryStatement( queryParameters, false, Collections.<AfterLoadAction>emptyList(), session );
final PreparedStatement st = (PreparedStatement) rs.getStatement();
final Iterator result = new IteratorImpl(
rs,

View File

@ -63,7 +63,7 @@ public class Array extends List {
public CollectionType getDefaultCollectionType() throws MappingException {
return getMappings().getTypeResolver()
.getTypeFactory()
.array( getRole(), getReferencedPropertyName(), isEmbedded(), getElementClass() );
.array( getRole(), getReferencedPropertyName(), getElementClass() );
}
@Override

View File

@ -39,7 +39,7 @@ public class Bag extends Collection {
public CollectionType getDefaultCollectionType() {
return getMappings().getTypeResolver()
.getTypeFactory()
.bag( getRole(), getReferencedPropertyName(), isEmbedded() );
.bag( getRole(), getReferencedPropertyName() );
}
void createPrimaryKey() {

View File

@ -384,7 +384,7 @@ public abstract class Collection implements Fetchable, Value, Filterable {
else {
return mappings.getTypeResolver()
.getTypeFactory()
.customCollection( typeName, typeParameters, role, referencedPropertyName, isEmbedded() );
.customCollection( typeName, typeParameters, role, referencedPropertyName );
}
}
@ -612,10 +612,20 @@ public abstract class Collection implements Fetchable, Value, Filterable {
this.elementNodeName = elementNodeName;
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public boolean isEmbedded() {
return embedded;
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public void setEmbedded(boolean embedded) {
this.embedded = embedded;
}

View File

@ -38,7 +38,7 @@ public class IdentifierBag extends IdentifierCollection {
public CollectionType getDefaultCollectionType() {
return getMappings().getTypeResolver()
.getTypeFactory()
.idbag( getRole(), getReferencedPropertyName(), isEmbedded() );
.idbag( getRole(), getReferencedPropertyName() );
}
public Object accept(ValueVisitor visitor) {

View File

@ -79,7 +79,6 @@ public class Index implements RelationalModel, Serializable {
String defaultCatalog,
String defaultSchema
) {
//TODO handle supportsNotNullUnique=false, but such a case does not exist in the wild so far
StringBuilder buf = new StringBuilder( "create" )
.append( unique ?
" unique" :

View File

@ -46,7 +46,7 @@ public class List extends IndexedCollection {
public CollectionType getDefaultCollectionType() throws MappingException {
return getMappings().getTypeResolver()
.getTypeFactory()
.list( getRole(), getReferencedPropertyName(), isEmbedded() );
.list( getRole(), getReferencedPropertyName() );
}
public Object accept(ValueVisitor visitor) {

View File

@ -49,7 +49,6 @@ public class ManyToOne extends ToOne {
getReferencedPropertyName(),
isLazy(),
isUnwrapProxy(),
isEmbedded(),
isIgnoreNotFound(),
isLogicalOneToOne
);

View File

@ -44,17 +44,17 @@ public class Map extends IndexedCollection {
if ( isSorted() ) {
return getMappings().getTypeResolver()
.getTypeFactory()
.sortedMap( getRole(), getReferencedPropertyName(), isEmbedded(), getComparator() );
.sortedMap( getRole(), getReferencedPropertyName(), getComparator() );
}
else if ( hasOrder() ) {
return getMappings().getTypeResolver()
.getTypeFactory()
.orderedMap( getRole(), getReferencedPropertyName(), isEmbedded() );
.orderedMap( getRole(), getReferencedPropertyName() );
}
else {
return getMappings().getTypeResolver()
.getTypeFactory()
.map( getRole(), getReferencedPropertyName(), isEmbedded() );
.map( getRole(), getReferencedPropertyName() );
}
}

View File

@ -51,7 +51,6 @@ public class OneToMany implements Value {
null,
false,
false,
isEmbedded(),
isIgnoreNotFound(),
false
);
@ -150,11 +149,21 @@ public class OneToMany implements Value {
//TODO: we could just return all false...
throw new UnsupportedOperationException();
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public boolean isEmbedded() {
return embedded;
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public void setEmbedded(boolean embedded) {
this.embedded = embedded;
}

View File

@ -84,7 +84,6 @@ public class OneToOne extends ToOne {
referencedPropertyName,
isLazy(),
isUnwrapProxy(),
isEmbedded(),
entityName,
propertyName
);

View File

@ -61,17 +61,17 @@ public class Set extends Collection {
if ( isSorted() ) {
return getMappings().getTypeResolver()
.getTypeFactory()
.sortedSet( getRole(), getReferencedPropertyName(), isEmbedded(), getComparator() );
.sortedSet( getRole(), getReferencedPropertyName(), getComparator() );
}
else if ( hasOrder() ) {
return getMappings().getTypeResolver()
.getTypeFactory()
.orderedSet( getRole(), getReferencedPropertyName(), isEmbedded() );
.orderedSet( getRole(), getReferencedPropertyName() );
}
else {
return getMappings().getTypeResolver()
.getTypeFactory()
.set( getRole(), getReferencedPropertyName(), isEmbedded() );
.set( getRole(), getReferencedPropertyName() );
}
}

View File

@ -26,7 +26,6 @@ package org.hibernate.mapping;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -56,9 +55,9 @@ public class Table implements RelationalModel, Serializable {
private Map columns = new LinkedHashMap();
private KeyValue idValue;
private PrimaryKey primaryKey;
private Map indexes = new HashMap();
private Map foreignKeys = new HashMap();
private Map<String,UniqueKey> uniqueKeys = new HashMap<String,UniqueKey>();
private Map indexes = new LinkedHashMap();
private Map foreignKeys = new LinkedHashMap();
private Map<String,UniqueKey> uniqueKeys = new LinkedHashMap<String,UniqueKey>();
private final int uniqueInteger;
private boolean quoted;
private boolean schemaQuoted;
@ -423,11 +422,12 @@ public class Table implements RelationalModel, Serializable {
alter.append( " not null" );
}
boolean useUniqueConstraint = column.isUnique() &&
dialect.supportsUnique() &&
( column.isNullable() || dialect.supportsNotNullUnique() );
if ( useUniqueConstraint ) {
alter.append( " unique" );
if ( column.isUnique() ) {
UniqueKey uk = getOrCreateUniqueKey(
column.getQuotedName( dialect ) + '_' );
uk.addColumn( column );
alter.append( dialect.getUniqueDelegate()
.applyUniqueToColumn( column ) );
}
if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
@ -524,19 +524,15 @@ public class Table implements RelationalModel, Serializable {
}
}
boolean useUniqueConstraint = col.isUnique() &&
( col.isNullable() || dialect.supportsNotNullUnique() );
if ( useUniqueConstraint ) {
if ( dialect.supportsUnique() ) {
buf.append( " unique" );
}
else {
UniqueKey uk = getOrCreateUniqueKey( col.getQuotedName( dialect ) + '_' );
uk.addColumn( col );
}
if ( col.isUnique() ) {
UniqueKey uk = getOrCreateUniqueKey(
col.getQuotedName( dialect ) + '_' );
uk.addColumn( col );
buf.append( dialect.getUniqueDelegate()
.applyUniqueToColumn( col ) );
}
if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
buf.append( " check (" )
.append( col.getCheckConstraint() )
@ -558,21 +554,7 @@ public class Table implements RelationalModel, Serializable {
.append( getPrimaryKey().sqlConstraintString( dialect ) );
}
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
Iterator ukiter = getUniqueKeyIterator();
while ( ukiter.hasNext() ) {
UniqueKey uk = (UniqueKey) ukiter.next();
String constraint = uk.sqlConstraintString( dialect );
if ( constraint != null ) {
buf.append( ", " ).append( constraint );
}
}
}
/*Iterator idxiter = getIndexIterator();
while ( idxiter.hasNext() ) {
Index idx = (Index) idxiter.next();
buf.append(',').append( idx.sqlConstraintString(dialect) );
}*/
buf.append( dialect.getUniqueDelegate().applyUniquesToTable( this ) );
if ( dialect.supportsTableCheck() ) {
Iterator chiter = checkConstraints.iterator();

View File

@ -88,11 +88,21 @@ public abstract class ToOne extends SimpleValue implements Fetchable {
public Object accept(ValueVisitor visitor) {
return visitor.accept(this);
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public boolean isEmbedded() {
return embedded;
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public void setEmbedded(boolean embedded) {
this.embedded = embedded;
}

View File

@ -22,89 +22,39 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.mapping;
import java.util.Iterator;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.Mapping;
/**
* A relational unique key constraint
*
* @author Gavin King
* @author Brett Meyer
*/
public class UniqueKey extends Constraint {
public String sqlConstraintString(Dialect dialect) {
StringBuilder buf = new StringBuilder( "unique (" );
boolean hadNullableColumn = false;
Iterator iter = getColumnIterator();
while ( iter.hasNext() ) {
Column column = (Column) iter.next();
if ( !hadNullableColumn && column.isNullable() ) {
hadNullableColumn = true;
}
buf.append( column.getQuotedName( dialect ) );
if ( iter.hasNext() ) {
buf.append( ", " );
}
}
//do not add unique constraint on DB not supporting unique and nullable columns
return !hadNullableColumn || dialect.supportsNotNullUnique() ?
buf.append( ')' ).toString() :
null;
}
@Override
public String sqlConstraintString(
Dialect dialect,
String constraintName,
String defaultCatalog,
String defaultSchema) {
StringBuilder buf = new StringBuilder(
dialect.getAddUniqueConstraintString( constraintName )
).append( '(' );
Iterator iter = getColumnIterator();
boolean nullable = false;
while ( iter.hasNext() ) {
Column column = (Column) iter.next();
if ( !nullable && column.isNullable() ) nullable = true;
buf.append( column.getQuotedName( dialect ) );
if ( iter.hasNext() ) buf.append( ", " );
}
return !nullable || dialect.supportsNotNullUnique() ? buf.append( ')' ).toString() : null;
// return dialect.getUniqueDelegate().uniqueConstraintSql( this );
// Not used.
return "";
}
@Override
public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog, String defaultSchema) {
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
return super.sqlCreateString( dialect, p, defaultCatalog, defaultSchema );
}
else {
return Index.buildSqlCreateIndexString( dialect, getName(), getTable(), getColumnIterator(), true,
defaultCatalog, defaultSchema );
}
public String sqlCreateString(Dialect dialect, Mapping p,
String defaultCatalog, String defaultSchema) {
return dialect.getUniqueDelegate().applyUniquesOnAlter(
this, defaultCatalog, defaultSchema );
}
@Override
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
return super.sqlDropString( dialect, defaultCatalog, defaultSchema );
}
else {
return Index.buildSqlDropIndexString( dialect, getTable(), getName(), defaultCatalog, defaultSchema );
}
}
@Override
public boolean isGenerated(Dialect dialect) {
if ( dialect.supportsNotNullUnique() ) return true;
Iterator iter = getColumnIterator();
while ( iter.hasNext() ) {
if ( ( (Column) iter.next() ).isNullable() ) {
return false;
}
}
return true;
public String sqlDropString(Dialect dialect, String defaultCatalog,
String defaultSchema) {
return dialect.getUniqueDelegate().dropUniquesOnAlter(
this, defaultCatalog, defaultSchema );
}
}

View File

@ -50,6 +50,7 @@ public class Index extends AbstractConstraint implements Constraint {
protected String getGeneratedNamePrefix() {
return "IDX";
}
@Override
public String sqlConstraintStringInAlterTable(Dialect dialect) {
StringBuilder buf = new StringBuilder( " index (" );

View File

@ -57,6 +57,8 @@ import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.dialect.lock.LockingStrategy;
@ -158,7 +160,7 @@ public abstract class AbstractEntityPersister
private final EntityRegionAccessStrategy cacheAccessStrategy;
private final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy;
private final boolean isLazyPropertiesCacheable;
private final CacheEntryStructure cacheEntryStructure;
private final CacheEntryHelper cacheEntryHelper;
private final EntityMetamodel entityMetamodel;
private final EntityTuplizer entityTuplizer;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -511,9 +513,6 @@ public abstract class AbstractEntityPersister
this.cacheAccessStrategy = cacheAccessStrategy;
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable();
this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ?
new StructuredCacheEntry(this) :
new UnstructuredCacheEntry();
this.entityMetamodel = new EntityMetamodel( persistentClass, factory );
this.entityTuplizer = this.entityMetamodel.getTuplizer();
@ -788,6 +787,48 @@ public abstract class AbstractEntityPersister
temporaryIdTableName = persistentClass.getTemporaryIdTableName();
temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL();
this.cacheEntryHelper = buildCacheEntryHelper();
}
protected CacheEntryHelper buildCacheEntryHelper() {
if ( cacheAccessStrategy == null ) {
// the entity defined no caching...
return NoopCacheEntryHelper.INSTANCE;
}
if ( canUseReferenceCacheEntries() ) {
entityMetamodel.setLazy( false );
// todo : do we also need to unset proxy factory?
return new ReferenceCacheEntryHelper( this );
}
return factory.getSettings().isStructuredCacheEntriesEnabled()
? new StructuredCacheEntryHelper( this )
: new StandardCacheEntryHelper( this );
}
protected boolean canUseReferenceCacheEntries() {
// todo : should really validate that the cache access type is read-only
if ( ! factory.getSettings().isDirectReferenceCacheEntriesEnabled() ) {
return false;
}
// for now, limit this to just entities that:
// 1) are immutable
if ( entityMetamodel.isMutable() ) {
return false;
}
// 2) have no associations. Eventually we want to be a little more lenient with associations.
for ( Type type : getSubclassPropertyTypeClosure() ) {
if ( type.isAssociationType() ) {
return false;
}
}
return true;
}
@ -799,11 +840,10 @@ public abstract class AbstractEntityPersister
this.factory = factory;
this.cacheAccessStrategy = cacheAccessStrategy;
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
this.isLazyPropertiesCacheable = entityBinding.getHierarchyDetails().getCaching() != null
&& entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties();
this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled()
? new StructuredCacheEntry(this)
: new UnstructuredCacheEntry();
this.isLazyPropertiesCacheable =
entityBinding.getHierarchyDetails().getCaching() == null ?
false :
entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties();
this.entityMetamodel = new EntityMetamodel( entityBinding, factory );
this.entityTuplizer = this.entityMetamodel.getTuplizer();
int batch = entityBinding.getBatchSize();
@ -1143,6 +1183,8 @@ public abstract class AbstractEntityPersister
temporaryIdTableName = null;
temporaryIdTableDDL = null;
this.cacheEntryHelper = buildCacheEntryHelper();
}
protected static String getTemplateFromString(String string, SessionFactoryImplementor factory) {
@ -4039,10 +4081,16 @@ public abstract class AbstractEntityPersister
return cacheAccessStrategy;
}
@Override
public CacheEntryStructure getCacheEntryStructure() {
return cacheEntryStructure;
return cacheEntryHelper.getCacheEntryStructure();
}
@Override
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session) {
return cacheEntryHelper.buildCacheEntry( entity, state, version, session );
}
public boolean hasNaturalIdCache() {
return naturalIdRegionAccessStrategy != null;
}
@ -4899,7 +4947,6 @@ public abstract class AbstractEntityPersister
return 0;
}
Type[] getLazyPropertyTypes() {
return lazyPropertyTypes;
}
@ -4915,4 +4962,97 @@ public abstract class AbstractEntityPersister
String[][] getLazyPropertyColumnAliases() {
return lazyPropertyColumnAliases;
}
/**
* Consolidated these onto a single helper because the 2 pieces work in tandem.
*/
public static interface CacheEntryHelper {
public CacheEntryStructure getCacheEntryStructure();
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session);
}
private static class StandardCacheEntryHelper implements CacheEntryHelper {
private final EntityPersister persister;
private StandardCacheEntryHelper(EntityPersister persister) {
this.persister = persister;
}
@Override
public CacheEntryStructure getCacheEntryStructure() {
return UnstructuredCacheEntry.INSTANCE;
}
@Override
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session) {
return new StandardCacheEntryImpl(
state,
persister,
persister.hasUninitializedLazyProperties( entity ),
version,
session,
entity
);
}
}
private static class ReferenceCacheEntryHelper implements CacheEntryHelper {
private final EntityPersister persister;
private ReferenceCacheEntryHelper(EntityPersister persister) {
this.persister = persister;
}
@Override
public CacheEntryStructure getCacheEntryStructure() {
return UnstructuredCacheEntry.INSTANCE;
}
@Override
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session) {
return new ReferenceCacheEntryImpl( entity, persister.getEntityName() );
}
}
private static class StructuredCacheEntryHelper implements CacheEntryHelper {
private final EntityPersister persister;
private final StructuredCacheEntry structure;
private StructuredCacheEntryHelper(EntityPersister persister) {
this.persister = persister;
this.structure = new StructuredCacheEntry( persister );
}
@Override
public CacheEntryStructure getCacheEntryStructure() {
return structure;
}
@Override
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session) {
return new StandardCacheEntryImpl(
state,
persister,
persister.hasUninitializedLazyProperties( entity ),
version,
session,
entity
);
}
}
private static class NoopCacheEntryHelper implements CacheEntryHelper {
public static final NoopCacheEntryHelper INSTANCE = new NoopCacheEntryHelper();
@Override
public CacheEntryStructure getCacheEntryStructure() {
return UnstructuredCacheEntry.INSTANCE;
}
@Override
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session) {
throw new HibernateException( "Illegal attempt to build cache entry for non-cached entity" );
}
}
}

View File

@ -35,6 +35,7 @@ import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.cache.spi.OptimisticCacheSource;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -475,7 +476,9 @@ public interface EntityPersister extends OptimisticCacheSource {
* Get the cache structure
*/
public CacheEntryStructure getCacheEntryStructure();
public CacheEntry buildCacheEntry(Object entity, Object[] state, Object version, SessionImplementor session);
/**
* Does this class have a natural id cache
*/

View File

@ -47,6 +47,11 @@ public class ArrayType extends CollectionType {
private final Class elementClass;
private final Class arrayClass;
/**
* @deprecated Use {@link #ArrayType(TypeFactory.TypeScope, String, String, Class )} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public ArrayType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Class elementClass, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
this.elementClass = elementClass;
@ -57,6 +62,12 @@ public class ArrayType extends CollectionType {
return elementClass;
}
public ArrayType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Class elementClass) {
super( typeScope, role, propertyRef );
this.elementClass = elementClass;
arrayClass = Array.newInstance(elementClass, 0).getClass();
}
public Class getReturnedClass() {
return arrayClass;
}

View File

@ -85,7 +85,12 @@ public interface AssociationType extends Type {
* no columns to be updated?
*/
public abstract boolean isAlwaysDirtyChecked();
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public boolean isEmbeddedInXML();
}

View File

@ -35,10 +35,19 @@ import org.hibernate.persister.collection.CollectionPersister;
public class BagType extends CollectionType {
/**
* @deprecated Use {@link #BagType(TypeFactory.TypeScope, String, String )}
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public BagType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public BagType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key)
throws HibernateException {
return new PersistentBag(session);

View File

@ -79,6 +79,11 @@ public abstract class CollectionType extends AbstractType implements Association
private final String foreignKeyPropertyName;
private final boolean isEmbeddedInXML;
/**
* @deprecated Use {@link #CollectionType(TypeFactory.TypeScope, String, String)} instead
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType(TypeFactory.TypeScope typeScope, String role, String foreignKeyPropertyName, boolean isEmbeddedInXML) {
this.typeScope = typeScope;
this.role = role;
@ -86,6 +91,13 @@ public abstract class CollectionType extends AbstractType implements Association
this.isEmbeddedInXML = isEmbeddedInXML;
}
public CollectionType(TypeFactory.TypeScope typeScope, String role, String foreignKeyPropertyName) {
this.typeScope = typeScope;
this.role = role;
this.foreignKeyPropertyName = foreignKeyPropertyName;
this.isEmbeddedInXML = true;
}
public boolean isEmbeddedInXML() {
return isEmbeddedInXML;
}

View File

@ -48,6 +48,11 @@ public class CustomCollectionType extends CollectionType {
private final UserCollectionType userType;
private final boolean customLogging;
/**
* @deprecated Use {@link #CustomCollectionType(TypeFactory.TypeScope, Class, String, String )} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CustomCollectionType(
TypeFactory.TypeScope typeScope,
Class userTypeClass,
@ -55,13 +60,27 @@ public class CustomCollectionType extends CollectionType {
String foreignKeyPropertyName,
boolean isEmbeddedInXML) {
super( typeScope, role, foreignKeyPropertyName, isEmbeddedInXML );
userType = createUserCollectionType( userTypeClass );
customLogging = LoggableUserType.class.isAssignableFrom( userTypeClass );
}
public CustomCollectionType(
TypeFactory.TypeScope typeScope,
Class userTypeClass,
String role,
String foreignKeyPropertyName) {
super( typeScope, role, foreignKeyPropertyName );
userType = createUserCollectionType( userTypeClass );
customLogging = LoggableUserType.class.isAssignableFrom( userTypeClass );
}
private static UserCollectionType createUserCollectionType(Class userTypeClass) {
if ( !UserCollectionType.class.isAssignableFrom( userTypeClass ) ) {
throw new MappingException( "Custom type does not implement UserCollectionType: " + userTypeClass.getName() );
}
try {
userType = ( UserCollectionType ) userTypeClass.newInstance();
return ( UserCollectionType ) userTypeClass.newInstance();
}
catch ( InstantiationException ie ) {
throw new MappingException( "Cannot instantiate custom type: " + userTypeClass.getName() );
@ -69,8 +88,6 @@ public class CustomCollectionType extends CollectionType {
catch ( IllegalAccessException iae ) {
throw new MappingException( "IllegalAccessException trying to instantiate custom type: " + userTypeClass.getName() );
}
customLogging = LoggableUserType.class.isAssignableFrom( userTypeClass );
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key)

View File

@ -76,7 +76,11 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
* says to return the "implementation target" of lazy prooxies; typically only possible
* with lazy="no-proxy".
*
* @deprecated Use {@link #EntityType(TypeFactory.TypeScope, String, String, boolean, boolean )} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
protected EntityType(
TypeFactory.TypeScope scope,
String entityName,
@ -92,6 +96,32 @@ public abstract class EntityType extends AbstractType implements AssociationType
this.unwrapProxy = unwrapProxy;
}
/**
* Constructs the requested entity type mapping.
*
* @param scope The type scope
* @param entityName The name of the associated entity.
* @param uniqueKeyPropertyName The property-ref name, or null if we
* reference the PK of the associated entity.
* @param eager Is eager fetching enabled.
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
* says to return the "implementation target" of lazy prooxies; typically only possible
* with lazy="no-proxy".
*/
protected EntityType(
TypeFactory.TypeScope scope,
String entityName,
String uniqueKeyPropertyName,
boolean eager,
boolean unwrapProxy) {
this.scope = scope;
this.associatedEntityName = entityName;
this.uniqueKeyPropertyName = uniqueKeyPropertyName;
this.isEmbeddedInXML = true;
this.eager = eager;
this.unwrapProxy = unwrapProxy;
}
protected TypeFactory.TypeScope scope() {
return scope;
}
@ -451,6 +481,11 @@ public abstract class EntityType extends AbstractType implements AssociationType
}
}
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
protected boolean isNotEmbedded(SessionImplementor session) {
// return !isEmbeddedInXML;
return false;

View File

@ -34,10 +34,19 @@ import org.hibernate.persister.collection.CollectionPersister;
public class IdentifierBagType extends CollectionType {
/**
* @deprecated Use {@link #IdentifierBagType(org.hibernate.type.TypeFactory.TypeScope, String, String)}
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public IdentifierBagType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public IdentifierBagType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
public PersistentCollection instantiate(
SessionImplementor session,
CollectionPersister persister, Serializable key)

View File

@ -34,10 +34,19 @@ import org.hibernate.persister.collection.CollectionPersister;
public class ListType extends CollectionType {
/**
* @deprecated Use {@link #ListType(org.hibernate.type.TypeFactory.TypeScope, String, String)}
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public ListType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public ListType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key) {
return new PersistentList(session);
}

View File

@ -70,6 +70,12 @@ public class ManyToOneType extends EntityType {
this( scope, referencedEntityName, null, lazy, true, false, false, false );
}
/**
* @deprecated Use {@link #ManyToOneType(TypeFactory.TypeScope, String, String, boolean, boolean, boolean, boolean ) } instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public ManyToOneType(
TypeFactory.TypeScope scope,
String referencedEntityName,
@ -84,6 +90,19 @@ public class ManyToOneType extends EntityType {
this.isLogicalOneToOne = isLogicalOneToOne;
}
public ManyToOneType(
TypeFactory.TypeScope scope,
String referencedEntityName,
String uniqueKeyPropertyName,
boolean lazy,
boolean unwrapProxy,
boolean ignoreNotFound,
boolean isLogicalOneToOne) {
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
this.ignoreNotFound = ignoreNotFound;
this.isLogicalOneToOne = isLogicalOneToOne;
}
protected boolean isNullable() {
return ignoreNotFound;
}

View File

@ -37,10 +37,19 @@ import org.hibernate.persister.collection.CollectionPersister;
public class MapType extends CollectionType {
/**
* @deprecated Use {@link #MapType(TypeFactory.TypeScope, String, String ) } instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public MapType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public MapType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key) {
return new PersistentMap(session);
}

View File

@ -47,6 +47,12 @@ public class OneToOneType extends EntityType {
private final String propertyName;
private final String entityName;
/**
* @deprecated Use {@link #OneToOneType(TypeFactory.TypeScope, String, ForeignKeyDirection, String, boolean, boolean, String, String)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public OneToOneType(
TypeFactory.TypeScope scope,
String referencedEntityName,
@ -62,7 +68,22 @@ public class OneToOneType extends EntityType {
this.propertyName = propertyName;
this.entityName = entityName;
}
public OneToOneType(
TypeFactory.TypeScope scope,
String referencedEntityName,
ForeignKeyDirection foreignKeyType,
String uniqueKeyPropertyName,
boolean lazy,
boolean unwrapProxy,
String entityName,
String propertyName) {
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
this.foreignKeyType = foreignKeyType;
this.propertyName = propertyName;
this.entityName = entityName;
}
public String getPropertyName() {
return propertyName;
}

View File

@ -36,11 +36,20 @@ public class OrderedMapType extends MapType {
* @param role The collection role name.
* @param propertyRef The property ref name.
* @param isEmbeddedInXML Is this collection to embed itself in xml
*
* @deprecated Use {@link #OrderedMapType(TypeFactory.TypeScope, String, String)} instead.
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public OrderedMapType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public OrderedMapType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
/**
* {@inheritDoc}
*/

View File

@ -37,11 +37,20 @@ public class OrderedSetType extends SetType {
* @param role The collection role name.
* @param propertyRef The property ref name.
* @param isEmbeddedInXML Is this collection to embed itself in xml
*
* @deprecated Use {@link #OrderedSetType(org.hibernate.type.TypeFactory.TypeScope, String, String)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public OrderedSetType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public OrderedSetType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
/**
* {@inheritDoc}
*/

View File

@ -33,10 +33,19 @@ import org.hibernate.persister.collection.CollectionPersister;
public class SetType extends CollectionType {
/**
* @deprecated Use {@link #SetType(org.hibernate.type.TypeFactory.TypeScope, String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public SetType(TypeFactory.TypeScope typeScope, String role, String propertyRef, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
}
public SetType(TypeFactory.TypeScope typeScope, String role, String propertyRef) {
super( typeScope, role, propertyRef );
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key) {
return new PersistentSet(session);
}

View File

@ -37,11 +37,22 @@ public class SortedMapType extends MapType {
private final Comparator comparator;
/**
* @deprecated Use {@link #SortedMapType(org.hibernate.type.TypeFactory.TypeScope, String, String, java.util.Comparator)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public SortedMapType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Comparator comparator, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
this.comparator = comparator;
}
public SortedMapType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Comparator comparator) {
super( typeScope, role, propertyRef );
this.comparator = comparator;
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key) {
PersistentSortedMap map = new PersistentSortedMap(session);
map.setComparator(comparator);

View File

@ -35,11 +35,22 @@ import org.hibernate.persister.collection.CollectionPersister;
public class SortedSetType extends SetType {
private final Comparator comparator;
/**
* @deprecated Use {@link #SortedSetType(org.hibernate.type.TypeFactory.TypeScope, String, String, java.util.Comparator)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public SortedSetType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Comparator comparator, boolean isEmbeddedInXML) {
super( typeScope, role, propertyRef, isEmbeddedInXML );
this.comparator = comparator;
}
public SortedSetType(TypeFactory.TypeScope typeScope, String role, String propertyRef, Comparator comparator) {
super( typeScope, role, propertyRef );
this.comparator = comparator;
}
public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key) {
PersistentSortedSet set = new PersistentSortedSet(session);
set.setComparator(comparator);

View File

@ -29,8 +29,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import org.dom4j.Node;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.Mapping;
@ -166,8 +164,13 @@ public interface Type extends Serializable {
* @return The java type class handled by this type.
*/
public Class getReturnedClass();
/**
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@SuppressWarnings( {"UnusedDeclaration"})
@Deprecated
public boolean isXMLElement();
/**

View File

@ -155,6 +155,12 @@ public final class TypeFactory implements Serializable {
}
}
/**
* @deprecated Use {@link #customCollection(String, java.util.Properties, String, String)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType customCollection(
String typeName,
Properties typeParameters,
@ -175,6 +181,25 @@ public final class TypeFactory implements Serializable {
return result;
}
public CollectionType customCollection(
String typeName,
Properties typeParameters,
String role,
String propertyRef) {
Class typeClass;
try {
typeClass = ReflectHelper.classForName( typeName );
}
catch ( ClassNotFoundException cnfe ) {
throw new MappingException( "user collection type class not found: " + typeName, cnfe );
}
CustomCollectionType result = new CustomCollectionType( typeScope, typeClass, role, propertyRef );
if ( typeParameters != null ) {
injectParameters( result.getUserType(), typeParameters );
}
return result;
}
public CustomType custom(Class<UserType> typeClass, Properties parameters) {
return custom( typeClass, parameters, typeScope );
}
@ -209,6 +234,12 @@ public final class TypeFactory implements Serializable {
// one-to-one type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #oneToOne(String, ForeignKeyDirection, String, boolean, boolean, String, String)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public EntityType oneToOne(
String persistentClass,
ForeignKeyDirection foreignKeyType,
@ -222,6 +253,18 @@ public final class TypeFactory implements Serializable {
lazy, unwrapProxy, isEmbeddedInXML, entityName, propertyName );
}
public EntityType oneToOne(
String persistentClass,
ForeignKeyDirection foreignKeyType,
String uniqueKeyPropertyName,
boolean lazy,
boolean unwrapProxy,
String entityName,
String propertyName) {
return new OneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
lazy, unwrapProxy, entityName, propertyName );
}
public EntityType specialOneToOne(
String persistentClass,
ForeignKeyDirection foreignKeyType,
@ -245,6 +288,12 @@ public final class TypeFactory implements Serializable {
return new ManyToOneType( typeScope, persistentClass, lazy );
}
/**
* @deprecated Use {@link #manyToOne(String, String, boolean, boolean, boolean, boolean)}
* instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public EntityType manyToOne(
String persistentClass,
String uniqueKeyPropertyName,
@ -265,49 +314,155 @@ public final class TypeFactory implements Serializable {
);
}
public EntityType manyToOne(
String persistentClass,
String uniqueKeyPropertyName,
boolean lazy,
boolean unwrapProxy,
boolean ignoreNotFound,
boolean isLogicalOneToOne) {
return new ManyToOneType(
typeScope,
persistentClass,
uniqueKeyPropertyName,
lazy,
unwrapProxy,
ignoreNotFound,
isLogicalOneToOne
);
}
// collection type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #array(String, String, Class)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType array(String role, String propertyRef, boolean embedded, Class elementClass) {
return new ArrayType( typeScope, role, propertyRef, elementClass, embedded );
}
public CollectionType array(String role, String propertyRef, Class elementClass) {
return new ArrayType( typeScope, role, propertyRef, elementClass );
}
/**
* @deprecated Use {@link #list(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType list(String role, String propertyRef, boolean embedded) {
return new ListType( typeScope, role, propertyRef, embedded );
}
public CollectionType list(String role, String propertyRef) {
return new ListType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #bag(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType bag(String role, String propertyRef, boolean embedded) {
return new BagType( typeScope, role, propertyRef, embedded );
}
public CollectionType bag(String role, String propertyRef) {
return new BagType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #idbag(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType idbag(String role, String propertyRef, boolean embedded) {
return new IdentifierBagType( typeScope, role, propertyRef, embedded );
}
public CollectionType idbag(String role, String propertyRef) {
return new IdentifierBagType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #map(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType map(String role, String propertyRef, boolean embedded) {
return new MapType( typeScope, role, propertyRef, embedded );
}
public CollectionType map(String role, String propertyRef) {
return new MapType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #orderedMap(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType orderedMap(String role, String propertyRef, boolean embedded) {
return new OrderedMapType( typeScope, role, propertyRef, embedded );
}
public CollectionType orderedMap(String role, String propertyRef) {
return new OrderedMapType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #sortedMap(String, String, java.util.Comparator)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType sortedMap(String role, String propertyRef, boolean embedded, Comparator comparator) {
return new SortedMapType( typeScope, role, propertyRef, comparator, embedded );
}
public CollectionType sortedMap(String role, String propertyRef, Comparator comparator) {
return new SortedMapType( typeScope, role, propertyRef, comparator );
}
/**
* @deprecated Use {@link #set(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType set(String role, String propertyRef, boolean embedded) {
return new SetType( typeScope, role, propertyRef, embedded );
}
public CollectionType set(String role, String propertyRef) {
return new SetType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #orderedSet(String, String)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType orderedSet(String role, String propertyRef, boolean embedded) {
return new OrderedSetType( typeScope, role, propertyRef, embedded );
}
public CollectionType orderedSet(String role, String propertyRef) {
return new OrderedSetType( typeScope, role, propertyRef );
}
/**
* @deprecated Use {@link #sortedSet(String, String, java.util.Comparator)} instead.
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
*/
@Deprecated
public CollectionType sortedSet(String role, String propertyRef, boolean embedded, Comparator comparator) {
return new SortedSetType( typeScope, role, propertyRef, comparator, embedded );
}
public CollectionType sortedSet(String role, String propertyRef, Comparator comparator) {
return new SortedSetType( typeScope, role, propertyRef, comparator );
}
// component type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -30,6 +30,7 @@ import java.io.Reader;
import java.io.StringReader;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import org.jboss.logging.Logger;
@ -268,26 +269,41 @@ public class DataHelper {
/**
* Extract the contents of the given Clob as a string.
*
* @param reader The reader for the content
* @param value The clob to to be extracted from
*
* @return The content as string
*/
public static String extractString(final Clob value) {
try {
Reader characterStream = value.getCharacterStream();
long length = value.length();
if ( length > Integer.MAX_VALUE ) {
return extractString( characterStream, Integer.MAX_VALUE );
}
else {
return extractString( characterStream, (int) length );
}
final Reader characterStream = value.getCharacterStream();
final long length = determineLengthForBufferSizing( value );
return length > Integer.MAX_VALUE
? extractString( characterStream, Integer.MAX_VALUE )
: extractString( characterStream, (int) length );
}
catch ( SQLException e ) {
throw new HibernateException( "Unable to access lob stream", e );
}
}
/**
* Determine a buffer size for reading the underlying character stream.
*
* @param value The Clob value
*
* @return The appropriate buffer size ({@link java.sql.Clob#length()} by default.
*
* @throws SQLException
*/
private static long determineLengthForBufferSizing(Clob value) throws SQLException {
try {
return value.length();
}
catch ( SQLFeatureNotSupportedException e ) {
return BUFFER_SIZE;
}
}
/**
* Make sure we allocate a buffer sized not bigger than 2048,
* not higher than what is actually needed, and at least one.
@ -295,7 +311,7 @@ public class DataHelper {
* @param lengthHint the expected size of the full value
* @return the buffer size
*/
private static final int getSuggestedBufferSize(final int lengthHint) {
private static int getSuggestedBufferSize(final int lengthHint) {
return Math.max( 1, Math.min( lengthHint , BUFFER_SIZE ) );
}
}

View File

@ -1,179 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.id;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.TestingDatabaseInfo;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionImpl;
import org.hibernate.jdbc.Work;
import org.hibernate.mapping.SimpleAuxiliaryDatabaseObject;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.type.StandardBasicTypes;
import static org.junit.Assert.assertEquals;
/**
* I went back to 3.3 source and grabbed the code/logic as it existed back then and crafted this
* unit test so that we can make sure the value keep being generated in the expected manner
*
* @author Steve Ebersole
*/
@SuppressWarnings({ "deprecation" })
public class TableHiLoGeneratorTest extends BaseUnitTestCase {
private static final String GEN_TABLE = "generator_table";
private static final String GEN_COLUMN = TableHiLoGenerator.DEFAULT_COLUMN_NAME;
private Configuration cfg;
private ServiceRegistry serviceRegistry;
private SessionFactoryImplementor sessionFactory;
private TableHiLoGenerator generator;
@Before
public void setUp() throws Exception {
Properties properties = new Properties();
properties.setProperty( TableGenerator.TABLE, GEN_TABLE );
properties.setProperty( TableGenerator.COLUMN, GEN_COLUMN );
properties.setProperty( TableHiLoGenerator.MAX_LO, "3" );
properties.put(
PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
new ObjectNameNormalizer() {
@Override
protected boolean isUseQuotedIdentifiersGlobally() {
return false;
}
@Override
protected NamingStrategy getNamingStrategy() {
return cfg.getNamingStrategy();
}
}
);
Dialect dialect = new H2Dialect();
generator = new TableHiLoGenerator();
generator.configure( StandardBasicTypes.LONG, properties, dialect );
cfg = TestingDatabaseInfo.buildBaseConfiguration()
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" );
cfg.addAuxiliaryDatabaseObject(
new SimpleAuxiliaryDatabaseObject(
generator.sqlCreateStrings( dialect )[0],
generator.sqlDropStrings( dialect )[0]
)
);
cfg.addAuxiliaryDatabaseObject(
new SimpleAuxiliaryDatabaseObject(
generator.sqlCreateStrings( dialect )[1],
null
)
);
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() );
sessionFactory = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry );
}
@After
public void tearDown() throws Exception {
if ( sessionFactory != null ) {
sessionFactory.close();
}
if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry );
}
}
@Test
public void testHiLoAlgorithm() {
SessionImpl session = (SessionImpl) sessionFactory.openSession();
session.beginTransaction();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// initially sequence should be uninitialized
assertEquals( 0L, extractInDatabaseValue( session ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Long generatedValue = (Long) generator.generate( session, null );
assertEquals( 1L, generatedValue.longValue() );
assertEquals( 1L, extractInDatabaseValue( session ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generatedValue = (Long) generator.generate( session, null );
assertEquals( 2L, generatedValue.longValue() );
assertEquals( 1L, extractInDatabaseValue( session ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generatedValue = (Long) generator.generate( session, null );
assertEquals( 3L, generatedValue.longValue() );
assertEquals( 1L, extractInDatabaseValue( session ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generatedValue = (Long) generator.generate( session, null );
assertEquals( 4L, generatedValue.longValue() );
assertEquals( 2L, extractInDatabaseValue( session ) );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generatedValue = (Long) generator.generate( session, null );
assertEquals( 5L, generatedValue.longValue() );
assertEquals( 2L, extractInDatabaseValue( session ) );
session.getTransaction().commit();
session.close();
}
private long extractInDatabaseValue(Session session) {
class WorkImpl implements Work {
private long value;
public void execute(Connection connection) throws SQLException {
PreparedStatement query = connection.prepareStatement( "select " + GEN_COLUMN + " from " + GEN_TABLE );
ResultSet resultSet = query.executeQuery();
resultSet.next();
value = resultSet.getLong( 1 );
}
}
WorkImpl work = new WorkImpl();
session.doWork( work );
return work.value;
}
}

Some files were not shown because too many files have changed in this diff Show More