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:
commit
c33fdae563
|
@ -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>
|
||||
|
|
|
@ -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>.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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() ) {
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
|
75
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/ReferenceCacheEntryImpl.java
vendored
Normal file
75
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/ReferenceCacheEntryImpl.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
170
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StandardCacheEntryImpl.java
vendored
Normal file
170
hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StandardCacheEntryImpl.java
vendored
Normal 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 );
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,10 +217,6 @@ public class H2Dialect extends Dialect {
|
|||
return " for update";
|
||||
}
|
||||
|
||||
public boolean supportsUnique() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -251,10 +251,6 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean supportsUnique() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
*/
|
||||
|
|
|
@ -577,4 +577,8 @@ public class Oracle8iDialect extends Dialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useFollowOnLocking() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -422,10 +422,6 @@ public class SybaseASE15Dialect extends SybaseDialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getCrossJoinSeparator() {
|
||||
return ", ";
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ) ) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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" :
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -49,7 +49,6 @@ public class ManyToOne extends ToOne {
|
|||
getReferencedPropertyName(),
|
||||
isLazy(),
|
||||
isUnwrapProxy(),
|
||||
isEmbedded(),
|
||||
isIgnoreNotFound(),
|
||||
isLogicalOneToOne
|
||||
);
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ public class OneToOne extends ToOne {
|
|||
referencedPropertyName,
|
||||
isLazy(),
|
||||
isUnwrapProxy(),
|
||||
isEmbedded(),
|
||||
entityName,
|
||||
propertyName
|
||||
);
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 (" );
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
*/
|
||||
|
|
|
@ -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}
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue