You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(22) |
Nov
(308) |
Dec
(131) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(369) |
Feb
(171) |
Mar
(236) |
Apr
(187) |
May
(218) |
Jun
(217) |
Jul
(127) |
Aug
(448) |
Sep
(270) |
Oct
(231) |
Nov
(422) |
Dec
(255) |
2004 |
Jan
(111) |
Feb
(73) |
Mar
(338) |
Apr
(351) |
May
(349) |
Jun
(495) |
Jul
(394) |
Aug
(1048) |
Sep
(499) |
Oct
(142) |
Nov
(269) |
Dec
(638) |
2005 |
Jan
(825) |
Feb
(1272) |
Mar
(593) |
Apr
(690) |
May
(950) |
Jun
(958) |
Jul
(767) |
Aug
(839) |
Sep
(525) |
Oct
(449) |
Nov
(585) |
Dec
(455) |
2006 |
Jan
(603) |
Feb
(656) |
Mar
(195) |
Apr
(114) |
May
(136) |
Jun
(100) |
Jul
(128) |
Aug
(68) |
Sep
(7) |
Oct
(1) |
Nov
(1) |
Dec
(8) |
2007 |
Jan
(4) |
Feb
(3) |
Mar
(8) |
Apr
(16) |
May
(5) |
Jun
(4) |
Jul
(6) |
Aug
(23) |
Sep
(15) |
Oct
(5) |
Nov
(7) |
Dec
(5) |
2008 |
Jan
(5) |
Feb
(1) |
Mar
(1) |
Apr
(5) |
May
(1) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(1) |
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(2) |
2013 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2017 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <hib...@li...> - 2006-07-24 10:52:08
|
Author: max...@jb... Date: 2006-07-24 06:52:04 -0400 (Mon, 24 Jul 2006) New Revision: 10138 Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java Log: proper naming Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-07-24 10:51:54 UTC (rev 10137) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-07-24 10:52:04 UTC (rev 10138) @@ -168,7 +168,7 @@ s.close(); } - public void testParameterTypeMismatchFails() { + public void testParameterTypeMismatchFailureExpected() { Session s = openSession(); s.beginTransaction(); @@ -291,7 +291,7 @@ s.close(); } - public void testFetchInSubqueryFails() { + public void testFetchInSubqueryFailureExpected() { Session s = openSession(); try { s.createQuery( "from Animal a where a.mother in (select m from Animal a1 inner join a1.mother as m join fetch m.mother)" ).list(); |
From: <hib...@li...> - 2006-07-24 10:51:58
|
Author: max...@jb... Date: 2006-07-24 06:51:54 -0400 (Mon, 24 Jul 2006) New Revision: 10137 Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java Log: mingled order of types in exception message Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java =================================================================== --- branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-07-24 10:46:07 UTC (rev 10136) +++ branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-07-24 10:51:54 UTC (rev 10137) @@ -519,8 +519,8 @@ catch( ClassCastException cce ) { throw new TypeMismatchException( "named parameter [" + name + "] not of expected type; expected = " + - typedval.getValue().getClass().getName() + "; but was =" + - typedval.getType().getReturnedClass() + typedval.getType().getReturnedClass() + "; but was =" + + typedval.getValue().getClass().getName() ); } } |
From: <hib...@li...> - 2006-07-24 10:46:10
|
Author: max...@jb... Date: 2006-07-24 06:46:07 -0400 (Mon, 24 Jul 2006) New Revision: 10136 Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/ForeignKeys.java Log: HHH-1924 ForeignKeys: TransientObjectException is thrown without a message because of a wrong bracket in the code Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/ForeignKeys.java =================================================================== --- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-07-24 10:37:21 UTC (rev 10135) +++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-07-24 10:46:07 UTC (rev 10136) @@ -218,7 +218,7 @@ if ( isTransient(entityName, object, Boolean.FALSE, session) ) { throw new TransientObjectException( "object references an unsaved transient instance - save the transient instance before flushing: " + - entityName == null ? session.guessEntityName( object ) : entityName + (entityName == null ? session.guessEntityName( object ) : entityName) ); } id = session.getEntityPersister( entityName, object ).getIdentifier( object, session.getEntityMode() ); |
From: <hib...@li...> - 2006-07-24 10:37:33
|
Author: max...@jb... Date: 2006-07-24 06:37:21 -0400 (Mon, 24 Jul 2006) New Revision: 10135 Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java Log: proper naming Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-07-24 10:36:54 UTC (rev 10134) +++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-07-24 10:37:21 UTC (rev 10135) @@ -168,7 +168,7 @@ s.close(); } - public void testParameterTypeMismatchFails() { + public void testParameterTypeMismatchFailureExpected() { Session s = openSession(); s.beginTransaction(); |
From: <hib...@li...> - 2006-07-24 10:37:03
|
Author: max...@jb... Date: 2006-07-24 06:36:54 -0400 (Mon, 24 Jul 2006) New Revision: 10134 Modified: trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java Log: mingled order of types in exception message Modified: trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-07-24 10:35:25 UTC (rev 10133) +++ trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-07-24 10:36:54 UTC (rev 10134) @@ -519,8 +519,8 @@ catch( ClassCastException cce ) { throw new TypeMismatchException( "named parameter [" + name + "] not of expected type; expected = " + - typedval.getValue().getClass().getName() + "; but was =" + - typedval.getType().getReturnedClass() + typedval.getType().getReturnedClass() + "; but was =" + + typedval.getValue().getClass().getName() ); } } |
From: <hib...@li...> - 2006-07-24 10:35:38
|
Author: max...@jb... Date: 2006-07-24 06:35:25 -0400 (Mon, 24 Jul 2006) New Revision: 10133 Modified: trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java Log: HHH-1924 ForeignKeys: TransientObjectException is thrown without a message because of a wrong bracket in the code Modified: trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-07-21 16:53:54 UTC (rev 10132) +++ trunk/Hibernate3/src/org/hibernate/engine/ForeignKeys.java 2006-07-24 10:35:25 UTC (rev 10133) @@ -218,7 +218,7 @@ if ( isTransient(entityName, object, Boolean.FALSE, session) ) { throw new TransientObjectException( "object references an unsaved transient instance - save the transient instance before flushing: " + - entityName == null ? session.guessEntityName( object ) : entityName + (entityName == null ? session.guessEntityName( object ) : entityName) ); } id = session.getEntityPersister( entityName, object ).getIdentifier( object, session.getEntityMode() ); |
From: <hib...@li...> - 2006-07-21 16:54:29
|
Author: ste...@jb... Date: 2006-07-21 12:53:54 -0400 (Fri, 21 Jul 2006) New Revision: 10132 Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/MergeTest.java Log: port fix for HHH-1927 to 3.2 branch Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java =================================================================== --- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-21 16:52:30 UTC (rev 10131) +++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-21 16:53:54 UTC (rev 10132) @@ -17,6 +17,8 @@ import org.hibernate.event.MergeEvent; import org.hibernate.event.MergeEventListener; import org.hibernate.engine.SessionImplementor; +import org.hibernate.engine.EntityEntry; +import org.hibernate.engine.EntityKey; import org.hibernate.intercept.FieldInterceptionHelper; import org.hibernate.intercept.FieldInterceptor; import org.hibernate.persister.entity.EntityPersister; @@ -85,14 +87,33 @@ event.setResult(entity); } else { - event.setEntity(entity); - - int entityState = getEntityState( - entity, - event.getEntityName(), - source.getPersistenceContext().getEntry(entity), - source - ); + event.setEntity( entity ); + int entityState = -1; + + // Check the persistence context for an entry relating to this + // entity to be merged... + EntityEntry entry = source.getPersistenceContext().getEntry( entity ); + if ( entry == null ) { + EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + Object managedEntity = source.getPersistenceContext().getEntity( key ); + entry = source.getPersistenceContext().getEntry( managedEntity ); + if ( entry != null ) { + // we have specialized case of a detached entity from the + // perspective of the merge operation. Specifically, we + // have an incoming entity instance which has a corresponding + // entry in the current persistence context, but registered + // under a different entity instance + entityState = DETACHED; + } + } + } + + if ( entityState == -1 ) { + entityState = getEntityState( entity, event.getEntityName(), entry, source ); + } switch (entityState) { case DETACHED: @@ -263,13 +284,50 @@ } private boolean isVersionChanged(Object entity, EventSource source, EntityPersister persister, Object target) { - return persister.isVersioned() && - !persister.getVersionType().isSame( - persister.getVersion( target, source.getEntityMode() ), - persister.getVersion( entity, source.getEntityMode() ), - source.getEntityMode() - ); + if ( ! persister.isVersioned() ) { + return false; + } + // for merging of versioned entities, we consider the version having + // been changed only when: + // 1) the two version values are different; + // *AND* + // 2) The target actually represents database state! + // + // This second condition is a special case which allows + // an entity to be merged during the same transaction + // (though during a seperate operation) in which it was + // originally persisted/saved + boolean changed = persister.getVersionType().isSame( + persister.getVersion( target, source.getEntityMode() ), + persister.getVersion( entity, source.getEntityMode() ), + source.getEntityMode() + ); + + // TODO : perhaps we should additionally require that the incoming entity + // version be equivalent to the defined unsaved-value? + return changed && existsInDatabase( target, source, persister ); } + + private boolean existsInDatabase(Object entity, EventSource source, EntityPersister persister) { + EntityEntry entry = source.getPersistenceContext().getEntry( entity ); + if ( entry == null ) { + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + Object managedEntity = source.getPersistenceContext().getEntity( key ); + entry = source.getPersistenceContext().getEntry( managedEntity ); + } + } + + if ( entry == null ) { + // perhaps this should be an exception since it is only ever used + // in the above method? + return false; + } + else { + return entry.isExistsInDatabase(); + } + } protected void copyValues( final EntityPersister persister, Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/MergeTest.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-21 16:52:30 UTC (rev 10131) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-21 16:53:54 UTC (rev 10132) @@ -9,6 +9,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.NonUniqueObjectException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Projections; @@ -22,6 +23,58 @@ public MergeTest(String str) { super(str); } + + public void testPersistThenMergeInSameTxnWithVersion() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + VersionedEntity entity = new VersionedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new VersionedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new VersionedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } + + public void testPersistThenMergeInSameTxnWithTimestamp() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + TimestampedEntity entity = new TimestampedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new TimestampedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } public void testMergeDeepTree() { @@ -330,7 +383,7 @@ } protected String[] getMappings() { - return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml" }; + return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml", "ops/OptLockEntity.hbm.xml" }; } public static Test suite() { Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-21 16:52:30 UTC (rev 10131) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-21 16:53:54 UTC (rev 10132) @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD 3.0//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + +<!-- + +--> + +<hibernate-mapping package="org.hibernate.test.ops"> + + <class name="VersionedEntity" table="V_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <version name="version" column="VERS" type="long" /> + <property name="name" column="NAME" type="string" /> + </class> + + <class name="TimestampedEntity" table="T_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <timestamp name="timestamp" column="TS" /> + <property name="name" column="NAME" type="string" /> + </class> + +</hibernate-mapping> + Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-21 16:52:30 UTC (rev 10131) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-21 16:53:54 UTC (rev 10132) @@ -0,0 +1,47 @@ +package org.hibernate.test.ops; + +import java.util.Date; + +/** + * todo: describe TimestampedEntity + * + * @author Steve Ebersole + */ +public class TimestampedEntity { + private String id; + private String name; + private Date timestamp; + + public TimestampedEntity() { + } + + public TimestampedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } +} + Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-21 16:52:30 UTC (rev 10131) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-21 16:53:54 UTC (rev 10132) @@ -0,0 +1,44 @@ +package org.hibernate.test.ops; + +/** + * todo: describe VersionedEntity + * + * @author Steve Ebersole + */ +public class VersionedEntity { + private String id; + private String name; + private long version; + + public VersionedEntity() { + } + + public VersionedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } +} |
From: <hib...@li...> - 2006-07-21 16:53:05
|
Author: ste...@jb... Date: 2006-07-21 12:52:30 -0400 (Fri, 21 Jul 2006) New Revision: 10131 Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java Log: different approach to HHH-1927 Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-21 07:10:41 UTC (rev 10130) +++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-21 16:52:30 UTC (rev 10131) @@ -453,24 +453,6 @@ EntityEntry entry, //pass this as an argument only to avoid double looking SessionImplementor source) { - if ( entry == null && performDeepStateChecking() ) { - // check to handle fringe case of merging the same "entity data" via - // a transient instance within the same transaction it was saved; i.e.: - // Session s = ...; - // s.beginTransaction(); - // s.persist( new Entity( "someid" ) ); - // s.merge( new Entity( "someid" ) ); - // s.getTransaction().commit(); - EntityPersister persister = source.getEntityPersister( entityName, entity ); - Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); - if ( id != null ) { - EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); - entry = source.getPersistenceContext().getEntry( - source.getPersistenceContext().getEntity( key ) - ); - } - } - if ( entry != null ) { // the object is persistent as it has an entry associated with the // session; so check its status @@ -529,8 +511,4 @@ protected Boolean getAssumedUnsaved() { return null; } - - protected boolean performDeepStateChecking() { - return false; - } } Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-21 07:10:41 UTC (rev 10130) +++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-21 16:52:30 UTC (rev 10131) @@ -17,6 +17,8 @@ import org.hibernate.event.MergeEvent; import org.hibernate.event.MergeEventListener; import org.hibernate.engine.SessionImplementor; +import org.hibernate.engine.EntityEntry; +import org.hibernate.engine.EntityKey; import org.hibernate.intercept.FieldInterceptionHelper; import org.hibernate.intercept.FieldInterceptor; import org.hibernate.persister.entity.EntityPersister; @@ -85,15 +87,36 @@ event.setResult(entity); } else { - event.setEntity(entity); - - int entityState = getEntityState( - entity, - event.getEntityName(), - source.getPersistenceContext().getEntry(entity), - source - ); - + + event.setEntity( entity ); + + int entityState = -1; + + // Check the persistence context for an entry relating to this + // entity to be merged... + EntityEntry entry = source.getPersistenceContext().getEntry( entity ); + if ( entry == null ) { + EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + Object managedEntity = source.getPersistenceContext().getEntity( key ); + entry = source.getPersistenceContext().getEntry( managedEntity ); + if ( entry != null ) { + // we have specialized case of a detached entity from the + // perspective of the merge operation. Specifically, we + // have an incoming entity instance which has a corresponding + // entry in the current persistence context, but registered + // under a different entity instance + entityState = DETACHED; + } + } + } + + if ( entityState == -1 ) { + entityState = getEntityState( entity, event.getEntityName(), entry, source ); + } + switch (entityState) { case DETACHED: entityIsDetached(event, copyCache); @@ -117,10 +140,6 @@ } - protected boolean performDeepStateChecking() { - return true; - } - protected void entityIsPersistent(MergeEvent event, Map copyCache) { log.trace("ignoring persistent instance"); @@ -151,7 +170,7 @@ final Serializable id = persister.hasIdentifierProperty() ? persister.getIdentifier( entity, source.getEntityMode() ) : null; - + final Object copy = persister.instantiate( id, source.getEntityMode() ); //TODO: should this be Session.instantiate(Persister, ...)? copyCache.put(entity, copy); //before cascade! @@ -267,14 +286,51 @@ } private boolean isVersionChanged(Object entity, EventSource source, EntityPersister persister, Object target) { - return persister.isVersioned() && - !persister.getVersionType().isSame( - persister.getVersion( target, source.getEntityMode() ), - persister.getVersion( entity, source.getEntityMode() ), - source.getEntityMode() - ); + if ( ! persister.isVersioned() ) { + return false; + } + // for merging of versioned entities, we consider the version having + // been changed only when: + // 1) the two version values are different; + // *AND* + // 2) The target actually represents database state! + // + // This second condition is a special case which allows + // an entity to be merged during the same transaction + // (though during a seperate operation) in which it was + // originally persisted/saved + boolean changed = persister.getVersionType().isSame( + persister.getVersion( target, source.getEntityMode() ), + persister.getVersion( entity, source.getEntityMode() ), + source.getEntityMode() + ); + + // TODO : perhaps we should additionally require that the incoming entity + // version be equivalent to the defined unsaved-value? + return changed && existsInDatabase( target, source, persister ); } - + + private boolean existsInDatabase(Object entity, EventSource source, EntityPersister persister) { + EntityEntry entry = source.getPersistenceContext().getEntry( entity ); + if ( entry == null ) { + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + Object managedEntity = source.getPersistenceContext().getEntity( key ); + entry = source.getPersistenceContext().getEntry( managedEntity ); + } + } + + if ( entry == null ) { + // perhaps this should be an exception since it is only ever used + // in the above method? + return false; + } + else { + return entry.isExistsInDatabase(); + } + } + protected void copyValues( final EntityPersister persister, final Object entity, |
From: <hib...@li...> - 2006-07-21 07:10:45
|
Author: chr...@jb... Date: 2006-07-21 03:10:41 -0400 (Fri, 21 Jul 2006) New Revision: 10130 Modified: trunk/Hibernate3/doc/reference/build.xml Log: Updated current status Modified: trunk/Hibernate3/doc/reference/build.xml =================================================================== --- trunk/Hibernate3/doc/reference/build.xml 2006-07-21 06:41:22 UTC (rev 10129) +++ trunk/Hibernate3/doc/reference/build.xml 2006-07-21 07:10:41 UTC (rev 10130) @@ -40,12 +40,13 @@ <!-- TRANSLATOR: Duplicate this line for your language --> <antcall target="lang.all"><param name="lang" value="en"/></antcall> - <antcall target="lang.all"><param name="lang" value="fr"/></antcall> - <antcall target="lang.all"><param name="lang" value="ko"/></antcall> + <!-- TODO: These translations need updating... <antcall target="lang.all"><param name="lang" value="zh-cn"/></antcall> - <!-- TODO: These translations need updating... <antcall target="lang.all"><param name="lang" value="es"/></antcall> - --> + <antcall target="lang.all"><param name="lang" value="ja"/></antcall> + <antcall target="lang.all"><param name="lang" value="ko"/></antcall> + <antcall target="lang.all"><param name="lang" value="fr"/></antcall> + --> </target> @@ -55,7 +56,8 @@ <!-- TRANSLATOR: Duplicate this line for your language --> <antcall target="lang.revdiff"><param name="lang" value="zh-cn"/></antcall> <antcall target="lang.revdiff"><param name="lang" value="es"/></antcall> - <antcall target="lang.revdiff"><param name="lang" value="ko"/></antcall> + <antcall target="lang.revdiff"><param name="lang" value="ja"/></antcall> + <antcall target="lang.revdiff"><param name="lang" value="ko"/></antcall> <antcall target="lang.revdiff"><param name="lang" value="fr"/></antcall> </target> |
From: <hib...@li...> - 2006-07-21 06:41:28
|
Author: chr...@jb... Date: 2006-07-21 02:41:22 -0400 (Fri, 21 Jul 2006) New Revision: 10129 Modified: trunk/Hibernate3/doc/reference/en/modules/tutorial.xml Log: HHH-1906 Modified: trunk/Hibernate3/doc/reference/en/modules/tutorial.xml =================================================================== --- trunk/Hibernate3/doc/reference/en/modules/tutorial.xml 2006-07-20 19:32:13 UTC (rev 10128) +++ trunk/Hibernate3/doc/reference/en/modules/tutorial.xml 2006-07-21 06:41:22 UTC (rev 10129) @@ -931,7 +931,7 @@ </sect2> - <sect2 id="tutorial-associations-working" revision="1"> + <sect2 id="tutorial-associations-working" revision="2"> <title>Working the association</title> <para> @@ -1020,7 +1020,8 @@ Long eventId = mgr.createAndStoreEvent("My Event", new Date()); Long personId = mgr.createAndStorePerson("Foo", "Bar"); mgr.addPersonToEvent(personId, eventId); - System.out.println("Added person " + personId + " to event " + eventId);]]></programlisting> + System.out.println("Added person " + personId + " to event " + eventId); +}]]></programlisting> <para> This was an example of an association between two equally important classes, two entities. |
From: <hib...@li...> - 2006-07-20 19:32:16
|
Author: scottmarlownovell Date: 2006-07-20 15:32:13 -0400 (Thu, 20 Jul 2006) New Revision: 10128 Modified: trunk/Hibernate3/build.xml Log: Increase max memory to 256m for junitsingle to fix out of memory error. Modified: trunk/Hibernate3/build.xml =================================================================== --- trunk/Hibernate3/build.xml 2006-07-20 19:19:21 UTC (rev 10127) +++ trunk/Hibernate3/build.xml 2006-07-20 19:32:13 UTC (rev 10128) @@ -641,7 +641,7 @@ <target name="junitsingle" depends="cleantestdb,compiletest" description="Run a single test suite (requires testname and jdbc.driver properties)"> <mkdir dir="${test.out.dir}"/> - <junit printsummary="yes" fork="yes" haltonfailure="yes" dir="${basedir}"> + <junit printsummary="yes" maxmemory="256M" fork="yes" haltonfailure="yes" dir="${basedir}"> <classpath> <pathelement path="${etc.dir}"/> <!-- pick up property resources from the 'etc' directory first --> <fileset dir="${lib.dir}"> |
From: <hib...@li...> - 2006-07-20 19:20:13
|
Author: ste...@jb... Date: 2006-07-20 15:19:21 -0400 (Thu, 20 Jul 2006) New Revision: 10127 Added: trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java Log: HHH-1927 : persist() and merge() in same txn Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -451,12 +451,29 @@ Object entity, String entityName, EntityEntry entry, //pass this as an argument only to avoid double looking - SessionImplementor source - ) { - - if ( entry!=null ) { // the object is persistent - - //the entity is associated with the session, so check its status + SessionImplementor source) { + + if ( entry == null && performDeepStateChecking() ) { + // check to handle fringe case of merging the same "entity data" via + // a transient instance within the same transaction it was saved; i.e.: + // Session s = ...; + // s.beginTransaction(); + // s.persist( new Entity( "someid" ) ); + // s.merge( new Entity( "someid" ) ); + // s.getTransaction().commit(); + EntityPersister persister = source.getEntityPersister( entityName, entity ); + Serializable id = persister.getIdentifier( entity, source.getEntityMode() ); + if ( id != null ) { + EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); + entry = source.getPersistenceContext().getEntry( + source.getPersistenceContext().getEntity( key ) + ); + } + } + + if ( entry != null ) { + // the object is persistent as it has an entry associated with the + // session; so check its status if ( entry.getStatus() != Status.DELETED ) { // do nothing for persistent instances if ( log.isTraceEnabled() ) { @@ -479,11 +496,10 @@ } } - else { // the object is transient or detached - - //the entity is not associated with the session, so - //try interceptor and unsaved-value - + else { + // the entity is not associated with the session, so the various + // unsaved-value algorithms to determine whether it is transient + // or detached if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) { if ( log.isTraceEnabled() ) { log.trace( @@ -514,4 +530,7 @@ return null; } + protected boolean performDeepStateChecking() { + return false; + } } Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -116,7 +116,11 @@ } } - + + protected boolean performDeepStateChecking() { + return true; + } + protected void entityIsPersistent(MergeEvent event, Map copyCache) { log.trace("ignoring persistent instance"); Modified: trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/MergeTest.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -2,6 +2,7 @@ package org.hibernate.test.ops; import java.util.ArrayList; +import java.util.Date; import junit.framework.Test; import junit.framework.TestSuite; @@ -9,6 +10,7 @@ import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.NonUniqueObjectException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.criterion.Projections; @@ -22,7 +24,59 @@ public MergeTest(String str) { super(str); } - + + public void testPersistThenMergeInSameTxnWithVersion() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + VersionedEntity entity = new VersionedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new VersionedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new VersionedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } + + public void testPersistThenMergeInSameTxnWithTimestamp() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + TimestampedEntity entity = new TimestampedEntity( "test", "test" ); + s.persist( entity ); + s.merge( new TimestampedEntity( "test", "test-2" ) ); + + try { + // control operation... + s.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) ); + fail( "saveOrUpdate() should fail here" ); + } + catch( NonUniqueObjectException expected ) { + // expected behavior + } + + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + s.delete( entity ); + tx.commit(); + s.close(); + } + public void testMergeDeepTree() { clearCounts(); @@ -330,7 +384,7 @@ } protected String[] getMappings() { - return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml" }; + return new String[] { "ops/Node.hbm.xml", "ops/Employer.hbm.xml", "ops/OptLockEntity.hbm.xml" }; } public static Test suite() { Added: trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/OptLockEntity.hbm.xml 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD 3.0//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + +<!-- + +--> + +<hibernate-mapping package="org.hibernate.test.ops"> + + <class name="VersionedEntity" table="V_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <version name="version" column="VERS" type="long" /> + <property name="name" column="NAME" type="string" /> + </class> + + <class name="TimestampedEntity" table="T_ENTITY"> + <id name="id" column="ID" type="string"> + <generator class="assigned"/> + </id> + <timestamp name="timestamp" column="TS" /> + <property name="name" column="NAME" type="string" /> + </class> + +</hibernate-mapping> + Added: trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/TimestampedEntity.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,47 @@ +package org.hibernate.test.ops; + +import java.util.Date; + +/** + * todo: describe TimestampedEntity + * + * @author Steve Ebersole + */ +public class TimestampedEntity { + private String id; + private String name; + private Date timestamp; + + public TimestampedEntity() { + } + + public TimestampedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } +} + Added: trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-20 17:27:30 UTC (rev 10126) +++ trunk/Hibernate3/test/org/hibernate/test/ops/VersionedEntity.java 2006-07-20 19:19:21 UTC (rev 10127) @@ -0,0 +1,44 @@ +package org.hibernate.test.ops; + +/** + * todo: describe VersionedEntity + * + * @author Steve Ebersole + */ +public class VersionedEntity { + private String id; + private String name; + private long version; + + public VersionedEntity() { + } + + public VersionedEntity(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } +} |
From: <hib...@li...> - 2006-07-20 17:27:33
|
Author: scottmarlownovell Date: 2006-07-20 13:27:30 -0400 (Thu, 20 Jul 2006) New Revision: 10126 Modified: trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java Log: Fix for HHH-1293. Switched to using InvocationHandler. Modified: trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-19 14:11:50 UTC (rev 10125) +++ trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-20 17:27:30 UTC (rev 10126) @@ -4,16 +4,19 @@ import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; +import java.util.ArrayList; +import java.util.Iterator; + import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.Factory; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; +import net.sf.cglib.proxy.InvocationHandler; import net.sf.cglib.proxy.NoOp; import org.hibernate.HibernateException; +import org.hibernate.LazyInitializationException; import org.hibernate.proxy.pojo.BasicLazyInitializer; import org.hibernate.proxy.HibernateProxy; import org.hibernate.engine.SessionImplementor; @@ -25,11 +28,8 @@ /** * A <tt>LazyInitializer</tt> implemented using the CGLIB bytecode generation library */ -public final class CGLIBLazyInitializer extends BasicLazyInitializer implements MethodInterceptor { +public final class CGLIBLazyInitializer extends BasicLazyInitializer implements InvocationHandler { - - private static final Class[] CALLBACK_TYPES = new Class[]{ MethodInterceptor.class,NoOp.class }; - private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() { public int accept(Method method) { if ( method.getParameterTypes().length == 0 && method.getName().equals("finalize") ){ @@ -49,7 +49,7 @@ final Method setIdentifierMethod, AbstractComponentType componentIdType, final Serializable id, final SessionImplementor session) throws HibernateException { // note: interfaces is assumed to already contain HibernateProxy.class - + try { final CGLIBLazyInitializer instance = new CGLIBLazyInitializer( entityName, @@ -59,16 +59,13 @@ getIdentifierMethod, setIdentifierMethod, componentIdType, - session + session ); - - final HibernateProxy proxy = (HibernateProxy) Enhancer.create( - interfaces.length == 1 ? persistentClass : null, - interfaces, - FINALIZE_FILTER, - new Callback[]{ instance, NoOp.INSTANCE } - ); - + + final HibernateProxy proxy; + Class factory = getProxyFactory(persistentClass, interfaces); + Enhancer.registerCallbacks(factory, new Callback[]{ instance, null }); + proxy = (HibernateProxy)factory.newInstance(); instance.constructed = true; return proxy; } @@ -84,7 +81,7 @@ final Method getIdentifierMethod, final Method setIdentifierMethod, final AbstractComponentType componentIdType, final Serializable id, final SessionImplementor session) throws HibernateException { - + final CGLIBLazyInitializer instance = new CGLIBLazyInitializer( entityName, persistentClass, @@ -93,17 +90,17 @@ getIdentifierMethod, setIdentifierMethod, componentIdType, - session + session ); - + final HibernateProxy proxy; try { - proxy = (HibernateProxy) factory.newInstance(); + Enhancer.registerCallbacks(factory, new Callback[]{ instance, null }); + proxy = (HibernateProxy)factory.newInstance(); } catch (Exception e) { throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), e ); } - ( (Factory) proxy ).setCallback( 0, instance ); instance.constructed = true; return proxy; @@ -111,28 +108,17 @@ public static Class getProxyFactory(Class persistentClass, Class[] interfaces) throws HibernateException { - // note: interfaces is assumed to already contain HibernateProxy.class - - try { - - Enhancer en = new Enhancer(); - en.setUseCache( false ); - en.setInterceptDuringConstruction( false ); - - en.setCallbackTypes( CALLBACK_TYPES ); - en.setCallbackFilter( FINALIZE_FILTER ); - - en.setSuperclass( interfaces.length == 1 ? persistentClass : null ); - en.setInterfaces( interfaces ); - - return en.createClass(); - - } - catch (Throwable t) { - LogFactory.getLog( BasicLazyInitializer.class ) - .error( "CGLIB Enhancement failed: " + persistentClass.getName(), t ); - throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), t ); - } + Enhancer e = new Enhancer(); + e.setSuperclass( interfaces.length == 1 ? persistentClass : null ); + e.setInterfaces(interfaces); + e.setCallbackTypes(new Class[]{ + InvocationHandler.class, + NoOp.class, + }); + e.setCallbackFilter(FINALIZE_FILTER); + e.setUseFactory(false); + e.setInterceptDuringConstruction( false ); + return e.createClass(); } private CGLIBLazyInitializer(final String entityName, final Class persistentClass, @@ -146,48 +132,80 @@ getIdentifierMethod, setIdentifierMethod, componentIdType, - session + session ); this.interfaces = interfaces; } - public Object intercept(final Object proxy, final Method method, final Object[] args, - final MethodProxy methodProxy) throws Throwable { + private static boolean isCastable(Class caster, Class castee) { + if ( castee.equals( caster ) ) { + return true; + } + List list = addCheckingTypes( caster, new ArrayList() ); + for ( Iterator iter = list.iterator(); iter.hasNext(); ) { + Class cl = ( Class ) iter.next(); + if ( castee.equals( cl ) ) { + return true; + } + } + return false; + } + + private static List addCheckingTypes(final Class type, final List list) { + Class superclass = type.getSuperclass(); + if ( superclass != null ) { + list.add( superclass ); + addCheckingTypes( superclass, list ); + } + Class[] interfaces = type.getInterfaces(); + for ( int i = 0; i < interfaces.length; ++i ) { + list.add( interfaces[i] ); + addCheckingTypes( interfaces[i], list ); + } + return list; + } + + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if ( constructed ) { - Object result = invoke( method, args, proxy ); if ( result == INVOKE_IMPLEMENTATION ) { Object target = getImplementation(); final Object returnValue; - if ( ReflectHelper.isPublic( persistentClass, method ) ) { - returnValue = methodProxy.invoke( target, args ); - } - else { - if ( !method.isAccessible() ) method.setAccessible( true ); - try { + try { + if ( ReflectHelper.isPublic( persistentClass, method ) ) { + if ( !isCastable( + target.getClass(), method + .getDeclaringClass() + ) ) { + throw new ClassCastException( + target.getClass() + .getName() + ); + } returnValue = method.invoke( target, args ); } - catch (InvocationTargetException ite) { - throw ite.getTargetException(); + else { + if ( !method.isAccessible() ) method.setAccessible( true ); + returnValue = method.invoke( target, args ); } + return returnValue == target ? proxy : returnValue; } - return returnValue == target ? proxy : returnValue; + catch (InvocationTargetException ite) { + throw ite.getTargetException(); + } } else { return result; } - } else { - // while constructor is running if ( method.getName().equals( "getHibernateLazyInitializer" ) ) { return this; } else { - return methodProxy.invokeSuper( proxy, args ); + throw new LazyInitializationException("unexpected case hit, method=" + method.getName()); } - } } |
From: <hib...@li...> - 2006-07-19 14:11:55
|
Author: ste...@jb... Date: 2006-07-19 10:11:50 -0400 (Wed, 19 Jul 2006) New Revision: 10125 Added: branches/Branch_3_2/Hibernate3/ Log: branched 3.2 Copied: branches/Branch_3_2/Hibernate3 (from rev 10124, trunk/Hibernate3) |
From: <hib...@li...> - 2006-07-19 14:10:30
|
Author: ste...@jb... Date: 2006-07-19 10:10:21 -0400 (Wed, 19 Jul 2006) New Revision: 10124 Added: branches/Branch_3_2/ Log: created 3.2 branch directory |
From: <hib...@li...> - 2006-07-16 09:19:54
|
Author: max...@jb... Date: 2006-07-16 05:19:49 -0400 (Sun, 16 Jul 2006) New Revision: 10123 Modified: trunk/HibernateExt/build.bat Log: Modified: trunk/HibernateExt/build.bat =================================================================== (Binary files differ) |
From: <hib...@li...> - 2006-07-14 09:42:43
|
Author: max...@jb... Date: 2006-07-14 05:42:39 -0400 (Fri, 14 Jul 2006) New Revision: 10122 Modified: trunk/Hibernate3/test/org/hibernate/test/TestCase.java Log: make the nightly build only fail if something unexpected occurs. Modified: trunk/Hibernate3/test/org/hibernate/test/TestCase.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/TestCase.java 2006-07-14 03:52:37 UTC (rev 10121) +++ trunk/Hibernate3/test/org/hibernate/test/TestCase.java 2006-07-14 09:42:39 UTC (rev 10122) @@ -3,7 +3,6 @@ import java.sql.Blob; import java.sql.Clob; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -379,4 +378,27 @@ protected SessionFactoryImplementor sfi() { return ( SessionFactoryImplementor ) getSessions(); } + + public void runBare() throws Throwable { + assertNotNull(getName()); + if(Boolean.getBoolean( "hibernate.test.validatefailureexpected" )) { + if(getName().endsWith( "FailureExpected" ) ) { + Throwable t = null; + try { + super.runBare(); + } catch(Throwable afe) { + t = afe; + } + if(t==null) { + fail("Test where marked as FailureExpected, but did not fail!"); + } else { + reportSkip( "ignoring *FailuredExpected methods", "Failed with: " + t.toString() ); + } + } else { + super.runBare(); + } + } else { + super.runBare(); + } + } } \ No newline at end of file |
From: <hib...@li...> - 2006-07-14 03:52:56
|
Author: ste...@jb... Date: 2006-07-13 23:52:37 -0400 (Thu, 13 Jul 2006) New Revision: 10121 Modified: trunk/Hibernate3/test/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java Log: oops Modified: trunk/Hibernate3/test/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java 2006-07-14 01:55:32 UTC (rev 10120) +++ trunk/Hibernate3/test/org/hibernate/test/dynamicentity/tuplizer/MyEntityTuplizer.java 2006-07-14 03:52:37 UTC (rev 10121) @@ -1,7 +1,7 @@ package org.hibernate.test.dynamicentity.tuplizer; -import org.hibernate.tuple.PojoEntityTuplizer; -import org.hibernate.tuple.EntityMetamodel; +import org.hibernate.tuple.entity.PojoEntityTuplizer; +import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.Instantiator; import org.hibernate.mapping.PersistentClass; import org.hibernate.proxy.ProxyFactory; @@ -9,7 +9,7 @@ import org.hibernate.property.Setter; /** - * @author <a href="mailto:st...@hi...">Steve Ebersole </a> + * @author Steve Ebersole */ public class MyEntityTuplizer extends PojoEntityTuplizer { |
From: <hib...@li...> - 2006-07-14 01:55:35
|
Author: ste...@jb... Date: 2006-07-13 21:55:32 -0400 (Thu, 13 Jul 2006) New Revision: 10120 Added: trunk/Hibernate3/test/org/hibernate/test/tm/DummyJTAStyleTransationFactory.java Log: oops Added: trunk/Hibernate3/test/org/hibernate/test/tm/DummyJTAStyleTransationFactory.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/tm/DummyJTAStyleTransationFactory.java 2006-07-14 00:09:19 UTC (rev 10119) +++ trunk/Hibernate3/test/org/hibernate/test/tm/DummyJTAStyleTransationFactory.java 2006-07-14 01:55:32 UTC (rev 10120) @@ -0,0 +1,138 @@ +package org.hibernate.test.tm; + +import org.hibernate.transaction.TransactionFactory; +import org.hibernate.Transaction; +import org.hibernate.HibernateException; +import org.hibernate.ConnectionReleaseMode; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.util.JTAHelper; +import org.hibernate.jdbc.JDBCContext; + +import javax.transaction.SystemException; +import javax.transaction.Synchronization; +import java.util.Properties; + +/** + * todo: describe DummyJTAStyleTransationFactory + * + * @author Steve Ebersole + */ +public class DummyJTAStyleTransationFactory implements TransactionFactory { + public Transaction createTransaction( + JDBCContext jdbcContext, + Context context) throws HibernateException { + return new DummyTransactionAdapter(); + } + + public void configure(Properties props) throws HibernateException { + } + + public ConnectionReleaseMode getDefaultReleaseMode() { + return ConnectionReleaseMode.AFTER_STATEMENT; + } + + public boolean isTransactionManagerRequired() { + return true; + } + + public boolean areCallbacksLocalToHibernateTransactions() { + return false; + } + + public boolean isTransactionInProgress( + JDBCContext jdbcContext, + Context transactionContext, + Transaction transaction) { + try { + return JTAHelper.isTransactionInProgress( DummyTransactionManager.INSTANCE.getCurrent() ) + && ! JTAHelper.isMarkedForRollback( DummyTransactionManager.INSTANCE.getCurrent() ); + } + catch( SystemException e ) { + throw new HibernateException( e ); + } + } + + private static class DummyTransactionAdapter implements Transaction { + + private boolean started; + private boolean committed; + private boolean rolledback; + + public void begin() throws HibernateException { + started = true; + committed = false; + rolledback = false; + try { + DummyTransactionManager.INSTANCE.begin(); + } + catch( Throwable t ) { + throw new HibernateException( "error on begin()", t ); + } + } + + public void commit() throws HibernateException { + if ( !started ) { + throw new HibernateException( "not yet started!" ); + } + started = false; + rolledback = false; + committed = false; + try { + DummyTransactionManager.INSTANCE.commit(); + committed = true; + } + catch( Throwable t ) { + throw new HibernateException( "error on commit()", t ); + } + } + + public void rollback() throws HibernateException { + if ( !started ) { + throw new HibernateException( "not yet started!" ); + } + started = false; + rolledback = false; + committed = false; + try { + DummyTransactionManager.INSTANCE.rollback(); + rolledback = true; + } + catch( Throwable t ) { + throw new HibernateException( "error on rollback()", t ); + } + } + + public boolean wasRolledBack() throws HibernateException { + return rolledback; + } + + public boolean wasCommitted() throws HibernateException { + return committed; + } + + public boolean isActive() throws HibernateException { + return started; + } + + public void registerSynchronization(Synchronization synchronization) throws HibernateException { + try { + DummyTransactionManager.INSTANCE.getCurrent().registerSynchronization( synchronization ); + } + catch( Throwable t ) { + throw new HibernateException( "error on registerSynchronization()", t ); + } + } + + public void setTimeout(int seconds) { + // ignore... + } + } + + public static void setup(Configuration cfg) { + cfg.setProperty( Environment.CONNECTION_PROVIDER, DummyConnectionProvider.class.getName() ); + cfg.setProperty( Environment.TRANSACTION_MANAGER_STRATEGY, DummyTransactionManagerLookup.class.getName() ); + cfg.setProperty( Environment.TRANSACTION_STRATEGY, DummyJTAStyleTransationFactory.class.getName() ); + cfg.setProperty( Environment.FLUSH_BEFORE_COMPLETION, "true" ); + } +} |
From: <hib...@li...> - 2006-07-14 00:15:14
|
Author: ste...@jb... Date: 2006-07-13 20:09:19 -0400 (Thu, 13 Jul 2006) New Revision: 10119 Added: trunk/Hibernate3/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java trunk/Hibernate3/src/org/hibernate/tuple/component/ trunk/Hibernate3/src/org/hibernate/tuple/component/AbstractComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/component/ComponentEntityModeToTuplizerMapping.java trunk/Hibernate3/src/org/hibernate/tuple/component/ComponentMetamodel.java trunk/Hibernate3/src/org/hibernate/tuple/component/ComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/component/Dom4jComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/component/PojoComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/entity/ trunk/Hibernate3/src/org/hibernate/tuple/entity/AbstractEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityEntityModeToTuplizerMapping.java trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/entity/PojoEntityTuplizer.java Removed: trunk/Hibernate3/src/org/hibernate/tuple/AbstractComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/AbstractEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/ComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/Dom4jComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/Dom4jEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/EntityMetamodel.java trunk/Hibernate3/src/org/hibernate/tuple/EntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/PojoComponentTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/PojoEntityTuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/TuplizerLookup.java Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java trunk/Hibernate3/src/org/hibernate/mapping/Component.java trunk/Hibernate3/src/org/hibernate/mapping/PersistentClass.java trunk/Hibernate3/src/org/hibernate/mapping/Subclass.java trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java trunk/Hibernate3/src/org/hibernate/tuple/PropertyFactory.java trunk/Hibernate3/src/org/hibernate/tuple/StandardProperty.java trunk/Hibernate3/src/org/hibernate/tuple/Tuplizer.java trunk/Hibernate3/src/org/hibernate/tuple/VersionProperty.java trunk/Hibernate3/src/org/hibernate/type/ComponentType.java trunk/Hibernate3/src/org/hibernate/type/EmbeddedComponentType.java Log: HHH-1907 : initial work Modified: trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/cfg/HbmBinder.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1755,11 +1755,20 @@ } - public static void bindComponent(Element node, Component component, String ownerClassName, - String parentProperty, String path, boolean isNullable, boolean isEmbedded, - Mappings mappings, java.util.Map inheritedMetas, boolean isIdentifierMapper) throws MappingException { + public static void bindComponent( + Element node, + Component component, + String ownerClassName, + String parentProperty, + String path, + boolean isNullable, + boolean isEmbedded, + Mappings mappings, + java.util.Map inheritedMetas, + boolean isIdentifierMapper) throws MappingException { component.setEmbedded( isEmbedded ); + component.setRoleName( path ); component.setMetaAttributes( getMetas( node, inheritedMetas ) ); Modified: trunk/Hibernate3/src/org/hibernate/mapping/Component.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/mapping/Component.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/mapping/Component.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -7,10 +7,8 @@ import java.util.Map; import org.hibernate.EntityMode; -import org.hibernate.FetchMode; import org.hibernate.MappingException; -import org.hibernate.engine.CascadeStyle; -import org.hibernate.tuple.TuplizerLookup; +import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.type.ComponentType; import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.Type; @@ -33,9 +31,30 @@ private Map metaAttributes; private String nodeName; private boolean isKey; + private String roleName; private java.util.Map tuplizerImpls; + public Component(PersistentClass owner) throws MappingException { + super( owner.getTable() ); + this.owner = owner; + } + + public Component(Component component) throws MappingException { + super( component.getTable() ); + this.owner = component.getOwner(); + } + + public Component(Join join) throws MappingException { + super( join.getTable() ); + this.owner = join.getPersistentClass(); + } + + public Component(Collection collection) throws MappingException { + super( collection.getCollectionTable() ); + this.owner = collection.getOwner(); + } + public int getPropertySpan() { return properties.size(); } @@ -67,26 +86,6 @@ return new JoinedIterator(iters); } - public Component(PersistentClass owner) throws MappingException { - super( owner.getTable() ); - this.owner = owner; - } - - public Component(Component component) throws MappingException { - super( component.getTable() ); - this.owner = component.getOwner(); - } - - public Component(Join join) throws MappingException { - super( join.getTable() ); - this.owner = join.getPersistentClass(); - } - - public Component(Collection collection) throws MappingException { - super( collection.getCollectionTable() ); - this.owner = collection.getOwner(); - } - public void setTypeByReflection(String propertyClass, String propertyName) {} public boolean isEmbedded() { @@ -149,49 +148,14 @@ } private Type buildType() { - final int span = getPropertySpan(); - String[] names = new String[span]; - org.hibernate.type.Type[] types = new org.hibernate.type.Type[span]; - boolean[] nullabilities = new boolean[span]; - CascadeStyle[] cascade = new CascadeStyle[span]; - FetchMode[] joinedFetch = new FetchMode[span]; - Iterator props = getPropertyIterator(); - int j=0; - while ( props.hasNext() ) { - Property prop = (Property) props.next(); - names[j] = prop.getName(); - types[j] = prop.getType(); - cascade[j] = prop.getCascadeStyle(); - joinedFetch[j] = prop.getValue().getFetchMode(); - nullabilities[j] = prop.isNullable(); - j++; - } - - TuplizerLookup tuplizers = TuplizerLookup.create(this); - + // TODO : temporary initial step towards HHH-1907 + ComponentMetamodel metamodel = new ComponentMetamodel( this ); if ( isEmbedded() ) { - return new EmbeddedComponentType( - names, - types, - nullabilities, - joinedFetch, - cascade, - isKey, - tuplizers - ); + return new EmbeddedComponentType( metamodel ); } else { - return new ComponentType( - names, - types, - nullabilities, - joinedFetch, - cascade, - isKey, - tuplizers - ); + return new ComponentType( metamodel ); } - } public void setTypeUsingReflection(String className, String propertyName) @@ -271,10 +235,20 @@ } public String getTuplizerImplClassName(EntityMode mode) { - if ( tuplizerImpls == null ) return null; + // todo : remove this once ComponentMetamodel is complete and merged + if ( tuplizerImpls == null ) { + return null; + } return ( String ) tuplizerImpls.get( mode ); } + public Map getTuplizerMap() { + if ( tuplizerImpls == null ) { + return null; + } + return java.util.Collections.unmodifiableMap( tuplizerImpls ); + } + public Property getProperty(String propertyName) throws MappingException { Iterator iter = getPropertyIterator(); while ( iter.hasNext() ) { @@ -286,6 +260,14 @@ throw new MappingException("component property not found: " + propertyName); } + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + public String toString() { return getClass().getName() + '(' + properties.toString() + ')'; } Modified: trunk/Hibernate3/src/org/hibernate/mapping/PersistentClass.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/mapping/PersistentClass.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/mapping/PersistentClass.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -2,12 +2,8 @@ package org.hibernate.mapping; import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; +import java.util.*; import java.util.Set; -import java.util.StringTokenizer; import org.hibernate.MappingException; import org.hibernate.EntityMode; @@ -712,7 +708,14 @@ if ( tuplizerImpls == null ) return null; return ( String ) tuplizerImpls.get( mode ); } - + + public java.util.Map getTuplizerMap() { + if ( tuplizerImpls == null ) { + return null; + } + return java.util.Collections.unmodifiableMap( tuplizerImpls ); + } + public boolean hasNaturalId() { Iterator props = getRootClass().getPropertyIterator(); while ( props.hasNext() ) { Modified: trunk/Hibernate3/src/org/hibernate/mapping/Subclass.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/mapping/Subclass.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/mapping/Subclass.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -151,7 +151,9 @@ } public void createForeignKey() { - if ( !isJoinedSubclass() ) throw new AssertionFailure("not a joined-subclass"); + if ( !isJoinedSubclass() ) { + throw new AssertionFailure( "not a joined-subclass" ); + } getKey().createForeignKeyOfEntity( getSuperclass().getEntityName() ); } @@ -226,6 +228,24 @@ return impl; } + public Map getTuplizerMap() { + Map specificTuplizerDefs = super.getTuplizerMap(); + Map superclassTuplizerDefs = getSuperclass().getTuplizerMap(); + if ( specificTuplizerDefs == null && superclassTuplizerDefs == null ) { + return null; + } + else { + Map combined = new HashMap(); + if ( superclassTuplizerDefs != null ) { + combined.putAll( superclassTuplizerDefs ); + } + if ( specificTuplizerDefs != null ) { + combined.putAll( specificTuplizerDefs ); + } + return java.util.Collections.unmodifiableMap( combined ); + } + } + public Component getIdentifierMapper() { return superclass.getIdentifierMapper(); } Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -2,11 +2,9 @@ package org.hibernate.persister.entity; import java.io.Serializable; -import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -73,8 +71,8 @@ import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.Template; import org.hibernate.sql.Update; -import org.hibernate.tuple.EntityMetamodel; -import org.hibernate.tuple.EntityTuplizer; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.Tuplizer; import org.hibernate.type.AbstractComponentType; import org.hibernate.type.AssociationType; Deleted: trunk/Hibernate3/src/org/hibernate/tuple/AbstractComponentTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/AbstractComponentTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/AbstractComponentTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,102 +0,0 @@ -//$Id$ -package org.hibernate.tuple; - -import java.lang.reflect.Method; -import java.util.Iterator; - -import org.hibernate.HibernateException; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; -import org.hibernate.property.Getter; -import org.hibernate.property.Setter; - -/** - * @author Gavin King - */ -public abstract class AbstractComponentTuplizer implements ComponentTuplizer { - - protected final Getter[] getters; - protected final Setter[] setters; - protected final int propertySpan; - protected final Instantiator instantiator; - protected final boolean hasCustomAccessors; - - protected abstract Instantiator buildInstantiator(Component component); - protected abstract Getter buildGetter(Component component, Property prop); - protected abstract Setter buildSetter(Component component, Property prop); - - protected AbstractComponentTuplizer(Component component) { - propertySpan = component.getPropertySpan(); - getters = new Getter[propertySpan]; - setters = new Setter[propertySpan]; - - Iterator iter = component.getPropertyIterator(); - boolean foundCustomAccessor=false; - int i=0; - while ( iter.hasNext() ) { - Property prop = (Property) iter.next(); - getters[i] = buildGetter(component, prop); - setters[i] = buildSetter(component, prop); - if ( !prop.isBasicPropertyAccessor() ) foundCustomAccessor = true; - i++; - } - hasCustomAccessors = foundCustomAccessor; - - String[] getterNames = new String[propertySpan]; - String[] setterNames = new String[propertySpan]; - Class[] propTypes = new Class[propertySpan]; - for ( int j = 0; j < propertySpan; j++ ) { - getterNames[j] = getters[j].getMethodName(); - setterNames[j] = setters[j].getMethodName(); - propTypes[j] = getters[j].getReturnType(); - } - instantiator = buildInstantiator(component); - } - - public Object getPropertyValue(Object component, int i) throws HibernateException { - return getters[i].get( component ); - } - - public Object[] getPropertyValues(Object component) throws HibernateException { - Object[] values = new Object[propertySpan]; - for ( int i = 0; i < propertySpan; i++ ) { - values[i] = getPropertyValue( component, i ); - } - return values; - } - - public boolean isInstance(Object object) { - return instantiator.isInstance(object); - } - - public void setPropertyValues(Object component, Object[] values) throws HibernateException { - for ( int i = 0; i < propertySpan; i++ ) { - setters[i].set( component, values[i], null ); - } - } - - /** - * This method does not populate the component parent - */ - public Object instantiate() throws HibernateException { - return instantiator.instantiate(); - } - - public Object getParent(Object component) { - return null; - } - - public boolean hasParentProperty() { - return false; - } - - public boolean isMethodOf(Method method) { - return false; - } - - public void setParent(Object component, Object parent, SessionFactoryImplementor factory) { - throw new UnsupportedOperationException(); - } - -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/AbstractEntityTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/AbstractEntityTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/AbstractEntityTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,403 +0,0 @@ -// $Id$ -package org.hibernate.tuple; - -import java.io.Serializable; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.id.Assigned; -import org.hibernate.intercept.LazyPropertyInitializer; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.property.Getter; -import org.hibernate.property.Setter; -import org.hibernate.proxy.ProxyFactory; -import org.hibernate.type.AbstractComponentType; -import org.hibernate.type.ComponentType; - - -/** - * Support base class for EntityTuplizer implementations. - * - * @author Steve Ebersole - */ -public abstract class AbstractEntityTuplizer implements EntityTuplizer { - - //TODO: currently keeps Getters and Setters (instead of PropertyAccessors) because of the way getGetter() and getSetter() are implemented currently; yuck! - - private final EntityMetamodel entityMetamodel; - - private final Getter idGetter; - private final Setter idSetter; - - protected final Getter[] getters; - protected final Setter[] setters; - protected final int propertySpan; - protected final boolean hasCustomAccessors; - private final Instantiator instantiator; - private final ProxyFactory proxyFactory; - private final AbstractComponentType identifierMapperType; - - - /** - * Return the entity-mode handled by this tuplizer instance. - * - * @return The entity-mode - */ - protected abstract EntityMode getEntityMode(); - - /** - * Build an appropriate Getter for the given property. - * - * @param mappedProperty The property to be accessed via the built Getter. - * @param mappedEntity The entity information regarding the mapped entity owning this property. - * @return An appropriate Getter instance. - */ - protected abstract Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity); - - /** - * Build an appropriate Setter for the given property. - * - * @param mappedProperty The property to be accessed via the built Setter. - * @param mappedEntity The entity information regarding the mapped entity owning this property. - * @return An appropriate Setter instance. - */ - protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity); - - /** - * Build an appropriate Instantiator for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @return An appropriate Instantiator instance. - */ - protected abstract Instantiator buildInstantiator(PersistentClass mappingInfo); - - /** - * Build an appropriate ProxyFactory for the given mapped entity. - * - * @param mappingInfo The mapping information regarding the mapped entity. - * @param idGetter The constructed Getter relating to the entity's id property. - * @param idSetter The constructed Setter relating to the entity's id property. - * @return An appropriate ProxyFactory instance. - */ - protected abstract ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter); - - /** - * Constructs a new AbstractEntityTuplizer instance. - * - * @param entityMetamodel The "interpreted" information relating to the mapped entity. - * @param mappingInfo The parsed "raw" mapping data relating to the given entity. - */ - public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) { - this.entityMetamodel = entityMetamodel; - - if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - idGetter = buildPropertyGetter( mappingInfo.getIdentifierProperty(), mappingInfo ); - idSetter = buildPropertySetter( mappingInfo.getIdentifierProperty(), mappingInfo ); - } - else { - idGetter = null; - idSetter = null; - } - - propertySpan = entityMetamodel.getPropertySpan(); - - getters = new Getter[propertySpan]; - setters = new Setter[propertySpan]; - - Iterator iter = mappingInfo.getPropertyClosureIterator(); - boolean foundCustomAccessor=false; - int i=0; - while ( iter.hasNext() ) { - //TODO: redesign how PropertyAccessors are acquired... - Property property = (Property) iter.next(); - getters[i] = buildPropertyGetter(property, mappingInfo); - setters[i] = buildPropertySetter(property, mappingInfo); - if ( !property.isBasicPropertyAccessor() ) foundCustomAccessor = true; - i++; - } - hasCustomAccessors = foundCustomAccessor; - - instantiator = buildInstantiator( mappingInfo ); - - if ( entityMetamodel.isLazy() ) { - proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter ); - } - else { - proxyFactory = null; - } - - Component mapper = mappingInfo.getIdentifierMapper(); - identifierMapperType = mapper==null ? null : (AbstractComponentType) mapper.getType(); - } - - /** Retreives the defined entity-name for the tuplized entity. - * - * @return The entity-name. - */ - protected String getEntityName() { - return entityMetamodel.getName(); - } - - /** - * Retreives the defined entity-names for any subclasses defined for this - * entity. - * - * @return Any subclass entity-names. - */ - protected Set getSubclassEntityNames() { - return entityMetamodel.getSubclassEntityNames(); - } - - public Serializable getIdentifier(Object entity) throws HibernateException { - final Object id; - if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { - id = entity; - } - else { - if ( idGetter == null ) { - if (identifierMapperType==null) { - throw new HibernateException( "The class has no identifier property: " + getEntityName() ); - } - else { - ComponentType copier = (ComponentType) entityMetamodel.getIdentifierProperty().getType(); - id = copier.instantiate( getEntityMode() ); - copier.setPropertyValues( id, identifierMapperType.getPropertyValues( entity, getEntityMode() ), getEntityMode() ); - } - } - else { - id = idGetter.get( entity ); - } - } - - try { - return (Serializable) id; - } - catch ( ClassCastException cce ) { - StringBuffer msg = new StringBuffer( "Identifier classes must be serializable. " ); - if ( id != null ) { - msg.append( id.getClass().getName() + " is not serializable. " ); - } - if ( cce.getMessage() != null ) { - msg.append( cce.getMessage() ); - } - throw new ClassCastException( msg.toString() ); - } - } - - - public void setIdentifier(Object entity, Serializable id) throws HibernateException { - if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) { - if ( entity != id ) { - AbstractComponentType copier = (AbstractComponentType) entityMetamodel.getIdentifierProperty().getType(); - copier.setPropertyValues( entity, copier.getPropertyValues( id, getEntityMode() ), getEntityMode() ); - } - } - else if ( idSetter != null ) { - idSetter.set( entity, id, getFactory() ); - } - } - - public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) { - if ( entityMetamodel.getIdentifierProperty().getIdentifierGenerator() instanceof Assigned ) { - //return currentId; - } - else { - //reset the id - Serializable result = entityMetamodel.getIdentifierProperty() - .getUnsavedValue() - .getDefaultValue( currentId ); - setIdentifier( entity, result ); - //reset the version - VersionProperty versionProperty = entityMetamodel.getVersionProperty(); - if ( entityMetamodel.isVersioned() ) { - setPropertyValue( - entity, - entityMetamodel.getVersionPropertyIndex(), - versionProperty.getUnsavedValue().getDefaultValue( currentVersion ) - ); - } - //return the id, so we can use it to reset the proxy id - //return result; - } - } - - public Object getVersion(Object entity) throws HibernateException { - if ( !entityMetamodel.isVersioned() ) return null; - return getters[ entityMetamodel.getVersionPropertyIndex() ].get( entity ); - } - - protected boolean shouldGetAllProperties(Object entity) { - return !hasUninitializedLazyProperties( entity ); - } - - public Object[] getPropertyValues(Object entity) throws HibernateException { - boolean getAll = shouldGetAllProperties( entity ); - final int span = entityMetamodel.getPropertySpan(); - final Object[] result = new Object[span]; - - for ( int j = 0; j < span; j++ ) { - StandardProperty property = entityMetamodel.getProperties()[j]; - if ( getAll || !property.isLazy() ) { - result[j] = getters[j].get( entity ); - } - else { - result[j] = LazyPropertyInitializer.UNFETCHED_PROPERTY; - } - } - return result; - } - - public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) - throws HibernateException { - final int span = entityMetamodel.getPropertySpan(); - final Object[] result = new Object[span]; - - for ( int j = 0; j < span; j++ ) { - result[j] = getters[j].getForInsert( entity, mergeMap, session ); - } - return result; - } - - public Object getPropertyValue(Object entity, int i) throws HibernateException { - return getters[i].get( entity ); - } - - public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException { - - int loc = propertyPath.indexOf('.'); - String basePropertyName = loc>0 ? - propertyPath.substring(0, loc) : propertyPath; - - int index = entityMetamodel.getPropertyIndex( basePropertyName ); - Object baseValue = getPropertyValue( entity, index ); - if ( loc>0 ) { - ComponentType type = (ComponentType) entityMetamodel.getPropertyTypes()[index]; - return getComponentValue( type, baseValue, propertyPath.substring(loc+1) ); - } - else { - return baseValue; - } - } - - /** - * Extract a component property value. - * - * @param type The component property types. - * @param component The component instance itself. - * @param propertyPath The property path for the property to be extracted. - * @return The property value extracted. - */ - protected Object getComponentValue(ComponentType type, Object component, String propertyPath) { - - int loc = propertyPath.indexOf('.'); - String basePropertyName = loc>0 ? - propertyPath.substring(0, loc) : propertyPath; - - String[] propertyNames = type.getPropertyNames(); - int index=0; - for ( ; index<propertyNames.length; index++ ) { - if ( basePropertyName.equals( propertyNames[index] ) ) break; - } - if (index==propertyNames.length) { - throw new MappingException( "component property not found: " + basePropertyName ); - } - - Object baseValue = type.getPropertyValue( component, index, getEntityMode() ); - - if ( loc>0 ) { - ComponentType subtype = (ComponentType) type.getSubtypes()[index]; - return getComponentValue( subtype, baseValue, propertyPath.substring(loc+1) ); - } - else { - return baseValue; - } - - } - - public void setPropertyValues(Object entity, Object[] values) throws HibernateException { - boolean setAll = !entityMetamodel.hasLazyProperties(); - - for ( int j = 0; j < entityMetamodel.getPropertySpan(); j++ ) { - if ( setAll || values[j] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) { - setters[j].set( entity, values[j], getFactory() ); - } - } - } - - public void setPropertyValue(Object entity, int i, Object value) throws HibernateException { - setters[i].set( entity, value, getFactory() ); - } - - public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException { - setters[ entityMetamodel.getPropertyIndex( propertyName ) ].set( entity, value, getFactory() ); - } - - public final Object instantiate(Serializable id) throws HibernateException { - Object result = getInstantiator().instantiate( id ); - if ( id != null ) { - setIdentifier( result, id ); - } - return result; - } - - public final Object instantiate() throws HibernateException { - return instantiate( null ); - } - - public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {} - - public boolean hasUninitializedLazyProperties(Object entity) { - // the default is to simply not lazy fetch properties for now... - return false; - } - - public final boolean isInstance(Object object) { - return getInstantiator().isInstance( object ); - } - - public boolean hasProxy() { - return entityMetamodel.isLazy(); - } - - public final Object createProxy(Serializable id, SessionImplementor session) - throws HibernateException { - return getProxyFactory().getProxy( id, session ); - } - - public boolean isLifecycleImplementor() { - return false; - } - - public boolean isValidatableImplementor() { - return false; - } - - protected final EntityMetamodel getEntityMetamodel() { - return entityMetamodel; - } - - protected final SessionFactoryImplementor getFactory() { - return entityMetamodel.getSessionFactory(); - } - - protected final Instantiator getInstantiator() { - return instantiator; - } - - protected final ProxyFactory getProxyFactory() { - return proxyFactory; - } - - public String toString() { - return getClass().getName() + '(' + getEntityMetamodel().getName() + ')'; - } - -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/ComponentTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/ComponentTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/ComponentTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,51 +0,0 @@ -//$Id$ -package org.hibernate.tuple; - -import java.io.Serializable; -import java.lang.reflect.Method; - -import org.hibernate.engine.SessionFactoryImplementor; - -/** - * Defines further responsibilities reagarding tuplization based on - * a mapped components. - * </p> - * ComponentTuplizer implementations should have the following constructor signature: - * (org.hibernate.mapping.Component) - * - * @author Gavin King - */ -public interface ComponentTuplizer extends Tuplizer, Serializable { - /** - * Retreive the current value of the parent property. - * - * @param component The component instance from which to extract the parent - * property value. - * @return The current value of the parent property. - */ - public Object getParent(Object component); - - /** - * Set the value of the parent property. - * - * @param component The component instance on which to set the parent. - * @param parent The parent to be set on the comonent. - * @param factory The current session factory. - */ - public void setParent(Object component, Object parent, SessionFactoryImplementor factory); - - /** - * Does the component managed by this tuuplizer contain a parent property? - * - * @return True if the component does contain a parent property; false otherwise. - */ - public boolean hasParentProperty(); - - /** - * Is the given method available via the managed component as a property getter? - * - * @param method The method which to check against the managed component. - * @return True if the managed component is available from the managed component; else false. - */ - public boolean isMethodOf(Method method); -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/Dom4jComponentTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/Dom4jComponentTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/Dom4jComponentTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,42 +0,0 @@ -//$Id$ -package org.hibernate.tuple; - -import org.dom4j.Element; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; -import org.hibernate.property.Getter; -import org.hibernate.property.PropertyAccessor; -import org.hibernate.property.PropertyAccessorFactory; -import org.hibernate.property.Setter; - -/** - * @author Gavin King - */ -public class Dom4jComponentTuplizer extends AbstractComponentTuplizer { - - public Class getMappedClass() { - return Element.class; - } - - public Dom4jComponentTuplizer(Component component) { - super(component); - } - - protected Instantiator buildInstantiator(Component component) { - return new Dom4jInstantiator( component ); - } - - private PropertyAccessor buildPropertyAccessor(Property property) { - //TODO: currently we don't know a SessionFactory reference when building the Tuplizer - // THIS IS A BUG (embedded-xml=false on component) - return PropertyAccessorFactory.getDom4jPropertyAccessor( property.getNodeName(), property.getType(), null ); - } - - protected Getter buildGetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getGetter( null, prop.getName() ); - } - protected Setter buildSetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getSetter( null, prop.getName() ); - } - -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/Dom4jEntityTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/Dom4jEntityTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/Dom4jEntityTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,120 +0,0 @@ -// $Id$ -package org.hibernate.tuple; - -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.proxy.ProxyFactory; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.dom4j.Dom4jProxyFactory; -import org.hibernate.property.PropertyAccessor; -import org.hibernate.property.PropertyAccessorFactory; -import org.hibernate.property.Getter; -import org.hibernate.property.Setter; -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.type.AbstractComponentType; -import org.dom4j.Element; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; -import java.util.Iterator; - -/** - * Implementation of Dom4jEntityTuplizer. - * - * @author Steve Ebersole - */ -public class Dom4jEntityTuplizer extends AbstractEntityTuplizer { - - static final Log log = LogFactory.getLog( Dom4jEntityTuplizer.class ); - - private Set subclassNodeNames = new HashSet(); - - Dom4jEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super(entityMetamodel, mappedEntity); - Iterator itr = mappedEntity.getSubclassClosureIterator(); - while( itr.hasNext() ) { - final PersistentClass mapping = ( PersistentClass ) itr.next(); - subclassNodeNames.add( mapping.getNodeName() ); - } - } - - public EntityMode getEntityMode() { - return EntityMode.DOM4J; - } - - private PropertyAccessor buildPropertyAccessor(Property mappedProperty) { - if ( mappedProperty.isBackRef() ) { - return mappedProperty.getPropertyAccessor(null); - } - else { - return PropertyAccessorFactory.getDom4jPropertyAccessor( - mappedProperty.getNodeName(), - mappedProperty.getType(), - getEntityMetamodel().getSessionFactory() - ); - } - } - - protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName() ); - } - - protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName() ); - } - - protected Instantiator buildInstantiator(PersistentClass persistentClass) { - return new Dom4jInstantiator( persistentClass ); - } - - public Serializable getIdentifier(Object entityOrId) throws HibernateException { - if (entityOrId instanceof Element) { - return super.getIdentifier(entityOrId); - } - else { - //it was not embedded, so the argument is just an id - return (Serializable) entityOrId; - } - } - - protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) { - HashSet proxyInterfaces = new HashSet(); - proxyInterfaces.add( HibernateProxy.class ); - proxyInterfaces.add( Element.class ); - - ProxyFactory pf = new Dom4jProxyFactory(); - try { - pf.postInstantiate( - getEntityName(), - Element.class, - proxyInterfaces, - null, - null, - mappingInfo.hasEmbeddedIdentifier() ? - (AbstractComponentType) mappingInfo.getIdentifier().getType() : - null - ); - } - catch ( HibernateException he ) { - log.warn( "could not create proxy factory for:" + getEntityName(), he ); - pf = null; - } - return pf; - } - - public Class getMappedClass() { - return Element.class; - } - - public Class getConcreteProxyClass() { - return Element.class; - } - - public boolean isInstrumented() { - return false; - } -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapComponentTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapComponentTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapComponentTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,42 +0,0 @@ -//$Id$ -package org.hibernate.tuple; - -import java.util.Map; - -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Property; -import org.hibernate.property.Getter; -import org.hibernate.property.PropertyAccessor; -import org.hibernate.property.PropertyAccessorFactory; -import org.hibernate.property.Setter; - -/** - * @author Gavin King - */ -public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer { - - public Class getMappedClass() { - return Map.class; - } - - protected Instantiator buildInstantiator(Component component) { - return new DynamicMapInstantiator(); - } - - public DynamicMapComponentTuplizer(Component component) { - super(component); - } - - private PropertyAccessor buildPropertyAccessor(Property property) { - return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - } - - protected Getter buildGetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getGetter( null, prop.getName() ); - } - - protected Setter buildSetter(Component component, Property prop) { - return buildPropertyAccessor(prop).getSetter( null, prop.getName() ); - } - -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapEntityTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapEntityTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/DynamicMapEntityTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,89 +0,0 @@ -// $Id$ -package org.hibernate.tuple; - -import java.util.Map; - -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.property.Getter; -import org.hibernate.property.PropertyAccessor; -import org.hibernate.property.PropertyAccessorFactory; -import org.hibernate.property.Setter; -import org.hibernate.proxy.map.MapProxyFactory; -import org.hibernate.proxy.ProxyFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Implementation of DynamicMapEntityTuplizer. - * - * @author Steve Ebersole - */ -public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer { - - static final Log log = LogFactory.getLog( DynamicMapEntityTuplizer.class ); - - DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { - super(entityMetamodel, mappedEntity); - } - - public EntityMode getEntityMode() { - return EntityMode.MAP; - } - - private PropertyAccessor buildPropertyAccessor(Property mappedProperty) { - if ( mappedProperty.isBackRef() ) { - return mappedProperty.getPropertyAccessor(null); - } - else { - return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - } - } - - protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName() ); - } - - protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { - return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName() ); - } - - protected Instantiator buildInstantiator(PersistentClass mappingInfo) { - return new DynamicMapInstantiator( mappingInfo ); - } - - protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) { - - ProxyFactory pf = new MapProxyFactory(); - try { - //TODO: design new lifecycle for ProxyFactory - pf.postInstantiate( - getEntityName(), - null, - null, - null, - null, - null - ); - } - catch ( HibernateException he ) { - log.warn( "could not create proxy factory for:" + getEntityName(), he ); - pf = null; - } - return pf; - } - - public Class getMappedClass() { - return Map.class; - } - - public Class getConcreteProxyClass() { - return Map.class; - } - - public boolean isInstrumented() { - return false; - } -} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/EntityMetamodel.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/EntityMetamodel.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/EntityMetamodel.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,481 +0,0 @@ -// $Id$ -package org.hibernate.tuple; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.intercept.FieldInterceptionHelper; -import org.hibernate.engine.CascadeStyle; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.engine.Versioning; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.type.AbstractComponentType; -import org.hibernate.type.AssociationType; -import org.hibernate.type.EntityType; -import org.hibernate.type.Type; -import org.hibernate.type.TypeFactory; -import org.hibernate.util.ArrayHelper; -import org.hibernate.util.ReflectHelper; - -/** - * Centralizes metamodel information about an entity. - * - * @author Steve Ebersole - */ -public class EntityMetamodel implements Serializable { - - private static final Log log = LogFactory.getLog(EntityMetamodel.class); - - private static final int NO_VERSION_INDX = -66; - - private final SessionFactoryImplementor sessionFactory; - - private final String name; - private final String rootName; - private final EntityType entityType; - - private final IdentifierProperty identifierProperty; - private final boolean versioned; - - private final int propertySpan; - private final int versionPropertyIndex; - private final StandardProperty[] properties; - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private final String[] propertyNames; - private final Type[] propertyTypes; - private final boolean[] propertyLaziness; - private final boolean[] propertyUpdateability; - private final boolean[] nonlazyPropertyUpdateability; - private final boolean[] propertyCheckability; - private final boolean[] propertyInsertability; - private final boolean[] propertyInsertGeneration; - private final boolean[] propertyUpdateGeneration; - private final boolean[] propertyNullability; - private final boolean[] propertyVersionability; - private final CascadeStyle[] cascadeStyles; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private final Map propertyIndexes = new HashMap(); - private final boolean hasCollections; - private final boolean hasMutableProperties; - private final boolean hasLazyProperties; - - private final int[] naturalIdPropertyNumbers; - - private final boolean lazy; - private final boolean hasCascades; - private final boolean mutable; - private final boolean isAbstract; - private final boolean selectBeforeUpdate; - private final boolean dynamicUpdate; - private final boolean dynamicInsert; - private final int optimisticLockMode; - - private final boolean polymorphic; - private final String superclass; // superclass entity-name - private final boolean explicitPolymorphism; - private final boolean inherited; - private final boolean hasSubclasses; - private final Set subclassEntityNames = new HashSet(); - - private final TuplizerLookup tuplizers; - - public EntityTuplizer getTuplizer(EntityMode entityMode) { - return (EntityTuplizer) tuplizers.getTuplizer(entityMode); - } - - public EntityTuplizer getTuplizerOrNull(EntityMode entityMode) { - return (EntityTuplizer) tuplizers.getTuplizerOrNull(entityMode); - } - - public EntityMode guessEntityMode(Object object) { - return tuplizers.guessEntityMode(object); - } - - public EntityMetamodel(PersistentClass persistentClass, SessionFactoryImplementor sessionFactory) { - this.sessionFactory = sessionFactory; - - name = persistentClass.getEntityName(); - rootName = persistentClass.getRootClass().getEntityName(); - entityType = TypeFactory.manyToOne( name ); - - identifierProperty = PropertyFactory.buildIdentifierProperty( - persistentClass, - sessionFactory.getIdentifierGenerator( rootName ) - ); - - versioned = persistentClass.isVersioned(); - - boolean lazyAvailable = persistentClass.hasPojoRepresentation() && - FieldInterceptionHelper.isInstrumented( persistentClass.getMappedClass() ); - boolean hasLazy = false; - - propertySpan = persistentClass.getPropertyClosureSpan(); - properties = new StandardProperty[propertySpan]; - List naturalIdNumbers = new ArrayList(); - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - propertyNames = new String[propertySpan]; - propertyTypes = new Type[propertySpan]; - propertyUpdateability = new boolean[propertySpan]; - propertyInsertability = new boolean[propertySpan]; - propertyInsertGeneration = new boolean[propertySpan]; - propertyUpdateGeneration = new boolean[propertySpan]; - nonlazyPropertyUpdateability = new boolean[propertySpan]; - propertyCheckability = new boolean[propertySpan]; - propertyNullability = new boolean[propertySpan]; - propertyVersionability = new boolean[propertySpan]; - propertyLaziness = new boolean[propertySpan]; - cascadeStyles = new CascadeStyle[propertySpan]; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - Iterator iter = persistentClass.getPropertyClosureIterator(); - int i = 0; - int tempVersionProperty = NO_VERSION_INDX; - boolean foundCascade = false; - boolean foundCollection = false; - boolean foundMutable = false; - - while ( iter.hasNext() ) { - Property prop = ( Property ) iter.next(); - - if ( prop == persistentClass.getVersion() ) { - tempVersionProperty = i; - properties[i] = PropertyFactory.buildVersionProperty( prop, lazyAvailable ); - } - else { - properties[i] = PropertyFactory.buildStandardProperty( prop, lazyAvailable ); - } - - if ( prop.isNaturalIdentifier() ) { - naturalIdNumbers.add( new Integer(i) ); - } - - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - boolean lazy = prop.isLazy() && lazyAvailable; - if ( lazy ) hasLazy = true; - propertyLaziness[i] = lazy; - - propertyNames[i] = properties[i].getName(); - propertyTypes[i] = properties[i].getType(); - propertyNullability[i] = properties[i].isNullable(); - propertyUpdateability[i] = properties[i].isUpdateable(); - propertyInsertability[i] = properties[i].isInsertable(); - propertyInsertGeneration[i] = properties[i].isInsertGenerated(); - propertyUpdateGeneration[i] = properties[i].isUpdateGenerated(); - propertyVersionability[i] = properties[i].isVersionable(); - nonlazyPropertyUpdateability[i] = properties[i].isUpdateable() && !lazy; - propertyCheckability[i] = propertyUpdateability[i] || - ( propertyTypes[i].isAssociationType() && ( (AssociationType) propertyTypes[i] ).isAlwaysDirtyChecked() ); - - cascadeStyles[i] = properties[i].getCascadeStyle(); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - if ( properties[i].isLazy() ) { - hasLazy = true; - } - - if ( properties[i].getCascadeStyle() != CascadeStyle.NONE ) { - foundCascade = true; - } - - if ( indicatesCollection( properties[i].getType() ) ) { - foundCollection = true; - } - - if ( propertyTypes[i].isMutable() && propertyCheckability[i] ) { - foundMutable = true; - } - - mapPropertyToIndex(prop, i); - i++; - } - - if (naturalIdNumbers.size()==0) { - naturalIdPropertyNumbers = null; - } - else { - naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); - } - - hasCascades = foundCascade; - versionPropertyIndex = tempVersionProperty; - hasLazyProperties = hasLazy; - if (hasLazyProperties) log.info("lazy property fetching available for: " + name); - - lazy = persistentClass.isLazy() && ( - // TODO: this disables laziness even in non-pojo entity modes: - !persistentClass.hasPojoRepresentation() || - !ReflectHelper.isFinalClass( persistentClass.getProxyInterface() ) - ); - mutable = persistentClass.isMutable(); - if ( persistentClass.isAbstract() == null ) { - // legacy behavior (with no abstract attribute specified) - isAbstract = persistentClass.hasPojoRepresentation() && - ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ); - } - else { - isAbstract = persistentClass.isAbstract().booleanValue(); - if ( !isAbstract && persistentClass.hasPojoRepresentation() && - ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ) ) { - log.warn( "entity [" + name + "] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names" ); - } - } - selectBeforeUpdate = persistentClass.hasSelectBeforeUpdate(); - dynamicUpdate = persistentClass.useDynamicUpdate(); - dynamicInsert = persistentClass.useDynamicInsert(); - - polymorphic = persistentClass.isPolymorphic(); - explicitPolymorphism = persistentClass.isExplicitPolymorphism(); - inherited = persistentClass.isInherited(); - superclass = inherited ? - persistentClass.getSuperclass().getEntityName() : - null; - hasSubclasses = persistentClass.hasSubclasses(); - - optimisticLockMode = persistentClass.getOptimisticLockMode(); - if ( optimisticLockMode > Versioning.OPTIMISTIC_LOCK_VERSION && !dynamicUpdate ) { - throw new MappingException( "optimistic-lock setting requires dynamic-update=\"true\": " + name ); - } - - hasCollections = foundCollection; - hasMutableProperties = foundMutable; - - tuplizers = TuplizerLookup.create(persistentClass, this); - - iter = persistentClass.getSubclassIterator(); - while ( iter.hasNext() ) { - subclassEntityNames.add( ( (PersistentClass) iter.next() ).getEntityName() ); - } - subclassEntityNames.add( name ); - - } - - private void mapPropertyToIndex(Property prop, int i) { - propertyIndexes.put( prop.getName(), new Integer(i) ); - if ( prop.getValue() instanceof Component ) { - Iterator iter = ( (Component) prop.getValue() ).getPropertyIterator(); - while ( iter.hasNext() ) { - Property subprop = (Property) iter.next(); - propertyIndexes.put( - prop.getName() + '.' + subprop.getName(), - new Integer(i) - ); - } - } - } - - public int[] getNaturalIdentifierProperties() { - return naturalIdPropertyNumbers; - } - - public boolean hasNaturalIdentifier() { - return naturalIdPropertyNumbers!=null; - } - - public Set getSubclassEntityNames() { - return subclassEntityNames; - } - - private boolean indicatesCollection(Type type) { - if ( type.isCollectionType() ) { - return true; - } - else if ( type.isComponentType() ) { - Type[] subtypes = ( ( AbstractComponentType ) type ).getSubtypes(); - for ( int i = 0; i < subtypes.length; i++ ) { - if ( indicatesCollection( subtypes[i] ) ) { - return true; - } - } - } - return false; - } - - public SessionFactoryImplementor getSessionFactory() { - return sessionFactory; - } - - public String getName() { - return name; - } - - public String getRootName() { - return rootName; - } - - public EntityType getEntityType() { - return entityType; - } - - public IdentifierProperty getIdentifierProperty() { - return identifierProperty; - } - - public int getPropertySpan() { - return propertySpan; - } - - public int getVersionPropertyIndex() { - return versionPropertyIndex; - } - - public VersionProperty getVersionProperty() { - if ( NO_VERSION_INDX == versionPropertyIndex ) { - return null; - } - else { - return ( VersionProperty ) properties[ versionPropertyIndex ]; - } - } - - public StandardProperty[] getProperties() { - return properties; - } - - public int getPropertyIndex(String propertyName) { - Integer index = getPropertyIndexOrNull(propertyName); - if ( index == null ) { - throw new HibernateException("Unable to resolve property: " + propertyName); - } - return index.intValue(); - } - - public Integer getPropertyIndexOrNull(String propertyName) { - return (Integer) propertyIndexes.get( propertyName ); - } - - public boolean hasCollections() { - return hasCollections; - } - - public boolean hasMutableProperties() { - return hasMutableProperties; - } - - public boolean hasLazyProperties() { - return hasLazyProperties; - } - - public boolean hasCascades() { - return hasCascades; - } - - public boolean isMutable() { - return mutable; - } - - public boolean isSelectBeforeUpdate() { - return selectBeforeUpdate; - } - - public boolean isDynamicUpdate() { - return dynamicUpdate; - } - - public boolean isDynamicInsert() { - return dynamicInsert; - } - - public int getOptimisticLockMode() { - return optimisticLockMode; - } - - public boolean isPolymorphic() { - return polymorphic; - } - - public String getSuperclass() { - return superclass; - } - - public boolean isExplicitPolymorphism() { - return explicitPolymorphism; - } - - public boolean isInherited() { - return inherited; - } - - public boolean hasSubclasses() { - return hasSubclasses; - } - - public boolean isLazy() { - return lazy; - } - - public boolean isVersioned() { - return versioned; - } - - public boolean isAbstract() { - return isAbstract; - } - - public String toString() { - return "EntityMetamodel(" + name + ':' + ArrayHelper.toString(properties) + ')'; - } - - // temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public String[] getPropertyNames() { - return propertyNames; - } - - public Type[] getPropertyTypes() { - return propertyTypes; - } - - public boolean[] getPropertyLaziness() { - return propertyLaziness; - } - - public boolean[] getPropertyUpdateability() { - return propertyUpdateability; - } - - public boolean[] getPropertyCheckability() { - return propertyCheckability; - } - - public boolean[] getNonlazyPropertyUpdateability() { - return nonlazyPropertyUpdateability; - } - - public boolean[] getPropertyInsertability() { - return propertyInsertability; - } - - public boolean[] getPropertyInsertGeneration() { - return propertyInsertGeneration; - } - - public boolean[] getPropertyUpdateGeneration() { - return propertyUpdateGeneration; - } - - public boolean[] getPropertyNullability() { - return propertyNullability; - } - - public boolean[] getPropertyVersionability() { - return propertyVersionability; - } - - public CascadeStyle[] getCascadeStyles() { - return cascadeStyles; - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -} Added: trunk/Hibernate3/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -0,0 +1,72 @@ +package org.hibernate.tuple; + +import org.apache.commons.collections.SequencedHashMap; + +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; + +import java.util.Map; +import java.util.Collections; +import java.util.Iterator; +import java.io.Serializable; + +/** + * Centralizes handling of {@link EntityMode} to {@link Tuplizer} mappings. + * + * @author Steve Ebersole + */ +public abstract class EntityModeToTuplizerMapping implements Serializable { + + // map of EntityMode -> Tuplizer + private final Map tuplizers = Collections.synchronizedMap( new SequencedHashMap() ); + + protected void addTuplizer(EntityMode entityMode, Tuplizer tuplizer) { + tuplizers.put( entityMode, tuplizer ); + } + + /** + * Given a supposed instance of an entity/component, guess its entity mode. + * + * @param object The supposed instance of the entity/component. + * @return The guessed entity mode. + */ + public EntityMode guessEntityMode(Object object) { + Iterator itr = tuplizers.entrySet().iterator(); + while( itr.hasNext() ) { + Map.Entry entry = ( Map.Entry ) itr.next(); + Tuplizer tuplizer = ( Tuplizer ) entry.getValue(); + if ( tuplizer.isInstance( object ) ) { + return ( EntityMode ) entry.getKey(); + } + } + return null; + } + + /** + * Locate the contained tuplizer responsible for the given entity-mode. If + * no such tuplizer is defined on this mapping, then return null. + * + * @param entityMode The entity-mode for which the caller wants a tuplizer. + * @return The tuplizer, or null if not found. + */ + public Tuplizer getTuplizerOrNull(EntityMode entityMode) { + return ( Tuplizer ) tuplizers.get( entityMode ); + } + + /** + * Locate the tuplizer contained within this mapping which is responsible + * for the given entity-mode. If no such tuplizer is defined on this + * mapping, then an exception is thrown. + * + * @param entityMode The entity-mode for which the caller wants a tuplizer. + * @return The tuplizer. + * @throws HibernateException Unable to locate the requested tuplizer. + */ + public Tuplizer getTuplizer(EntityMode entityMode) { + Tuplizer tuplizer = getTuplizerOrNull( entityMode ); + if ( tuplizer == null ) { + throw new HibernateException( "No tuplizer found for entity-mode [" + entityMode + "]"); + } + return tuplizer; + } +} Deleted: trunk/Hibernate3/src/org/hibernate/tuple/EntityTuplizer.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/tuple/EntityTuplizer.java 2006-07-13 21:38:41 UTC (rev 10118) +++ trunk/Hibernate3/src/org/hibernate/tuple/EntityTuplizer.java 2006-07-14 00:09:19 UTC (rev 10119) @@ -1,176 +0,0 @@ -//$Id$ -package org.hibernate.tuple; - -import java.io.Serializable; -import java.util.Map; - -import org.hibernate.HibernateException; -import org.hibernate.engine.SessionImplementor; - -/** - * Defines further responsibilities reagarding tuplization based on - * a mapped entity. - * <p/> - * EntityTuplizer implementations should have the following constructor signature: - * (org.hibernate.tuple.EntityMetamodel, org.hibernate.mapping.PersistentClass) - * - * @author Gavin King - */ -public interface EntityTuplizer extends Tuplizer { - - /** - * Create an entity instance initialized with the given identifier. - * - * @param id The identifier value for the entity to be instantiated. - * @return The instantiated entity. - * @throws HibernateException - */ - public Object instantiate(Serializable id) throws HibernateException; - - /** - * Extract the ide... [truncated message content] |
From: <hib...@li...> - 2006-07-13 21:39:30
|
Author: ste...@jb... Date: 2006-07-13 17:38:41 -0400 (Thu, 13 Jul 2006) New Revision: 10118 Modified: trunk/Hibernate3/src/org/hibernate/cache/OptimisticTreeCache.java trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java Log: corrections to OptimisticTreeCache; added some logging; formatting Modified: trunk/Hibernate3/src/org/hibernate/cache/OptimisticTreeCache.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cache/OptimisticTreeCache.java 2006-07-13 04:06:48 UTC (rev 10117) +++ trunk/Hibernate3/src/org/hibernate/cache/OptimisticTreeCache.java 2006-07-13 21:38:41 UTC (rev 10118) @@ -56,23 +56,15 @@ public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion) { try { - Option option = null; - if ( source != null ) { - if ( source.isVersioned() ) { - option = new Option(); - option.setDataVersion( - new DataVersionAdapter( - currentVersion, - previousVersion, - source.getVersionComparator() - ) - ); - } - } + Option option = new Option(); + DataVersion dv = ( source != null && source.isVersioned() ) + ? new DataVersionAdapter( currentVersion, previousVersion, source.getVersionComparator(), source.toString() ) + : NonLockingDataVersion.INSTANCE; + option.setDataVersion( dv ); cache.put( new Fqn( regionFqn, key ), ITEM, value, option ); } - catch (Exception e) { - throw new CacheException(e); + catch ( Exception e ) { + throw new CacheException( e ); } } @@ -80,18 +72,15 @@ try { Option option = new Option(); option.setFailSilently( true ); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); cache.remove( new Fqn( regionFqn, key ), "ITEM", option ); - if ( source != null ) { - if ( source.isVersioned() ) { - option.setDataVersion( - new DataVersionAdapter( - currentVersion, - null, - source.getVersionComparator() - ) - ); - } - } + + option = new Option(); + option.setFailSilently( true ); + DataVersion dv = ( source != null && source.isVersioned() ) + ? new DataVersionAdapter( currentVersion, currentVersion, source.getVersionComparator(), source.toString() ) + : NonLockingDataVersion.INSTANCE; + option.setDataVersion( dv ); cache.put( new Fqn( regionFqn, key ), ITEM, value, option ); } catch (Exception e) { @@ -106,6 +95,7 @@ try { Option option = new Option(); option.setFailSilently( true ); +// option.setDataVersion( NonLockingDataVersion.INSTANCE ); return cache.get( new Fqn( regionFqn, key ), ITEM, option ); } catch (Exception e) { @@ -124,7 +114,9 @@ public void update(Object key, Object value) throws CacheException { try { - cache.put( new Fqn( regionFqn, key ), ITEM, value ); + Option option = new Option(); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); + cache.put( new Fqn( regionFqn, key ), ITEM, value, option ); } catch (Exception e) { throw new CacheException(e); @@ -133,9 +125,11 @@ public void put(Object key, Object value) throws CacheException { try { + log.trace( "performing put() into region [" + regionName + "]" ); // do the put outside the scope of the JTA txn Option option = new Option(); option.setFailSilently( true ); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); cache.put( new Fqn( regionFqn, key ), ITEM, value, option ); } catch (TimeoutException te) { @@ -149,7 +143,16 @@ public void remove(Object key) throws CacheException { try { - cache.remove( new Fqn( regionFqn, key ) ); + // tree cache in optimistic mode seems to have as very difficult + // time with remove calls on non-existent nodes (NPEs)... + if ( cache.get( new Fqn( regionFqn, key ), ITEM ) != null ) { + Option option = new Option(); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); + cache.remove( new Fqn( regionFqn, key ), option ); + } + else { + log.trace( "skipping remove() call as the underlying node did not seem to exist" ); + } } catch (Exception e) { throw new CacheException(e); @@ -158,7 +161,9 @@ public void clear() throws CacheException { try { - cache.remove( regionFqn ); + Option option = new Option(); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); + cache.remove( regionFqn, option ); } catch (Exception e) { throw new CacheException(e); @@ -169,6 +174,8 @@ try { Option option = new Option(); option.setCacheModeLocal( true ); + option.setFailSilently( true ); + option.setDataVersion( NonLockingDataVersion.INSTANCE ); cache.remove( regionFqn, option ); } catch( Exception e ) { @@ -243,19 +250,80 @@ private final Object currentVersion; private final Object previousVersion; private final Comparator versionComparator; + private final String sourceIdentifer; - public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator) { + public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator, String sourceIdentifer) { this.currentVersion = currentVersion; this.previousVersion = previousVersion; this.versionComparator = versionComparator; + this.sourceIdentifer = sourceIdentifer; + log.trace( "created " + this ); } + /** + * newerThan() call is dispatched against the DataVersion currently + * associated with the node; the passed dataVersion param is the + * DataVersion associated with the data we are trying to put into + * the node. + * <p/> + * we are expected to return true in the case where we (the current + * node DataVersion) are newer that then incoming value. Returning + * true here essentially means that a optimistic lock failure has + * occured (because conversely, the value we are trying to put into + * the node is "older than" the value already there...) + */ public boolean newerThan(DataVersion dataVersion) { - if ( previousVersion == null ) { - log.warn( "Unexpected optimistic lock check on inserted data" ); + log.trace( "checking [" + this + "] against [" + dataVersion + "]" ); + if ( dataVersion instanceof CircumventChecksDataVersion ) { + log.trace( "skipping lock checks..." ); + return false; } - Object other = ( ( DataVersionAdapter ) dataVersion ).currentVersion; - return versionComparator.compare( previousVersion, other ) > 1; + else if ( dataVersion instanceof NonLockingDataVersion ) { + // can happen because of the multiple ways Cache.remove() + // can be invoked :( + log.trace( "skipping lock checks..." ); + return false; + } + DataVersionAdapter other = ( DataVersionAdapter ) dataVersion; + if ( other.previousVersion == null ) { + log.warn( "Unexpected optimistic lock check on inserting data" ); + // work around the "feature" where tree cache is validating the + // inserted node during the next transaction. no idea... + if ( this == dataVersion ) { + log.trace( "skipping lock checks due to same DV instance" ); + return false; + } + } + return versionComparator.compare( currentVersion, other.previousVersion ) >= 1; } + + public String toString() { + return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src=" + sourceIdentifer + "]"; + } } + + /** + * Used in regions where no locking should ever occur. This includes query-caches, + * update-timestamps caches, collection caches, and entity caches where the entity + * is not versioned. + */ + public static class NonLockingDataVersion implements DataVersion { + public static final DataVersion INSTANCE = new NonLockingDataVersion(); + public boolean newerThan(DataVersion dataVersion) { + log.trace( "non locking lock check..."); + return false; + } + } + + /** + * Used to signal to a DataVersionAdapter to simply not perform any checks. This + * is currently needed for proper handling of remove() calls for entity cache regions + * (we do not know the version info...). + */ + public static class CircumventChecksDataVersion implements DataVersion { + public static final DataVersion INSTANCE = new CircumventChecksDataVersion(); + public boolean newerThan(DataVersion dataVersion) { + throw new CacheException( "optimistic locking checks should never happen on CircumventChecksDataVersion" ); + } + } } Modified: trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java 2006-07-13 04:06:48 UTC (rev 10117) +++ trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java 2006-07-13 21:38:41 UTC (rev 10118) @@ -27,7 +27,7 @@ */ public class StandardQueryCache implements QueryCache { - private static final Log log = LogFactory.getLog(StandardQueryCache.class); + private static final Log log = LogFactory.getLog( StandardQueryCache.class ); private Cache queryCache; private UpdateTimestampsCache updateTimestampsCache; @@ -41,34 +41,40 @@ final Settings settings, final Properties props, final UpdateTimestampsCache updateTimestampsCache, - String regionName) - throws HibernateException { - - if (regionName==null) regionName = StandardQueryCache.class.getName(); + String regionName) throws HibernateException { + if ( regionName == null ) { + regionName = StandardQueryCache.class.getName(); + } String prefix = settings.getCacheRegionPrefix(); - if (prefix!=null) regionName = prefix + '.' + regionName; - - log.info("starting query cache at region: " + regionName); - + if ( prefix != null ) { + regionName = prefix + '.' + regionName; + } + log.info( "starting query cache at region: " + regionName ); + this.queryCache = settings.getCacheProvider().buildCache(regionName, props); this.updateTimestampsCache = updateTimestampsCache; this.regionName = regionName; } - public boolean put(QueryKey key, Type[] returnTypes, List result, boolean isNaturalKeyLookup, SessionImplementor session) - throws HibernateException { + public boolean put( + QueryKey key, + Type[] returnTypes, + List result, + boolean isNaturalKeyLookup, + SessionImplementor session) throws HibernateException { if ( isNaturalKeyLookup && result.size()==0 ) { return false; } else { - + Long ts = new Long( session.getTimestamp() ); + if ( log.isDebugEnabled() ) { - log.debug("caching query results in region: " + regionName); + log.debug( "caching query results in region: " + regionName + "; timestamp=" + ts ); } List cacheable = new ArrayList( result.size()+1 ); - cacheable.add( new Long( session.getTimestamp() ) ); + cacheable.add( ts ); for ( int i=0; i<result.size(); i++ ) { if ( returnTypes.length==1 ) { cacheable.add( returnTypes[0].disassemble( result.get(i), session, null ) ); @@ -86,25 +92,28 @@ } - public List get(QueryKey key, Type[] returnTypes, boolean isNaturalKeyLookup, Set spaces, SessionImplementor session) - throws HibernateException { - + public List get( + QueryKey key, + Type[] returnTypes, + boolean isNaturalKeyLookup, + Set spaces, + SessionImplementor session) throws HibernateException { if ( log.isDebugEnabled() ) { log.debug("checking cached query results in region: " + regionName); } - + List cacheable = (List) queryCache.get(key); if (cacheable==null) { log.debug("query results were not found in cache"); return null; } - + Long timestamp = (Long) cacheable.get(0); if ( !isNaturalKeyLookup && !isUpToDate(spaces, timestamp) ) { log.debug("cached query results were not up to date"); return null; } - + log.debug("returning cached query results"); for ( int i=1; i<cacheable.size(); i++ ) { if ( returnTypes.length==1 ) { Modified: trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java 2006-07-13 04:06:48 UTC (rev 10117) +++ trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java 2006-07-13 21:38:41 UTC (rev 10118) @@ -18,37 +18,37 @@ * to a higher value than the timeouts of any of the query caches. In fact, we * recommend that the the underlying cache not be configured for expiry at all. * Note, in particular, that an LRU cache expiry policy is never appropriate. - * @author Gavin King, Mikheil Kapanadze + * + * @author Gavin King + * @author Mikheil Kapanadze */ public class UpdateTimestampsCache { + public static final String REGION_NAME = UpdateTimestampsCache.class.getName(); + private static final Log log = LogFactory.getLog(UpdateTimestampsCache.class); private Cache updateTimestamps; private final String regionName; - public static final String REGION_NAME = UpdateTimestampsCache.class.getName(); - public void clear() throws CacheException { updateTimestamps.clear(); } - public UpdateTimestampsCache(Settings settings, Properties props) - throws HibernateException { + public UpdateTimestampsCache(Settings settings, Properties props) throws HibernateException { String prefix = settings.getCacheRegionPrefix(); - - regionName = prefix==null ? - REGION_NAME : - prefix + '.' + REGION_NAME; - log.info("starting update timestamps cache at region: " + regionName); - this.updateTimestamps = settings.getCacheProvider().buildCache(regionName, props); + regionName = prefix == null ? REGION_NAME : prefix + '.' + REGION_NAME; + log.info( "starting update timestamps cache at region: " + regionName ); + this.updateTimestamps = settings.getCacheProvider().buildCache( regionName, props ); } public synchronized void preinvalidate(Serializable[] spaces) throws CacheException { //TODO: to handle concurrent writes correctly, this should return a Lock to the client Long ts = new Long( updateTimestamps.nextTimestamp() + updateTimestamps.getTimeout() ); for ( int i=0; i<spaces.length; i++ ) { - if ( log.isDebugEnabled() ) log.debug("Pre-invalidating space [" + spaces[i] + "]"); + if ( log.isDebugEnabled() ) { + log.debug( "Pre-invalidating space [" + spaces[i] + "]" ); + } //put() has nowait semantics, is this really appropriate? //note that it needs to be async replication, never local or sync updateTimestamps.put( spaces[i], ts ); @@ -61,7 +61,9 @@ Long ts = new Long( updateTimestamps.nextTimestamp() ); //TODO: if lock.getTimestamp().equals(ts) for ( int i=0; i<spaces.length; i++ ) { - if ( log.isDebugEnabled() ) log.debug("Invalidating space [" + spaces[i] + "], timestamp: " + ts); + if ( log.isDebugEnabled() ) { + log.debug( "Invalidating space [" + spaces[i] + "], timestamp: " + ts); + } //put() has nowait semantics, is this really appropriate? //note that it needs to be async replication, never local or sync updateTimestamps.put( spaces[i], ts ); @@ -83,7 +85,8 @@ if ( log.isDebugEnabled() ) { log.debug("[" + space + "] last update timestamp: " + lastUpdate + ", result set timestamp: " + timestamp ); } - if ( lastUpdate.longValue() >= timestamp.longValue() ) return false; + return lastUpdate.longValue() < timestamp.longValue(); +// if ( lastUpdate.longValue() >= timestamp.longValue() ) return false; } } return true; |
From: <hib...@li...> - 2006-07-13 04:07:07
|
Author: ste...@jb... Date: 2006-07-13 00:06:48 -0400 (Thu, 13 Jul 2006) New Revision: 10117 Modified: branches/Hibernate_3_1_3_JBAS-3375/Hibernate3/src/org/hibernate/engine/transaction/Isolater.java Log: applied appropriate changeset (http://fisheye.jboss.com/changelog/Hibernate?cs=9919) Modified: branches/Hibernate_3_1_3_JBAS-3375/Hibernate3/src/org/hibernate/engine/transaction/Isolater.java =================================================================== --- branches/Hibernate_3_1_3_JBAS-3375/Hibernate3/src/org/hibernate/engine/transaction/Isolater.java 2006-07-13 03:31:21 UTC (rev 10116) +++ branches/Hibernate_3_1_3_JBAS-3375/Hibernate3/src/org/hibernate/engine/transaction/Isolater.java 2006-07-13 04:06:48 UTC (rev 10117) @@ -186,8 +186,8 @@ catch( Throwable ignore ) { log.trace( "was unable to reset connection back to auto-commit" ); } - session.getBatcher().closeConnection( connection ); } + session.getBatcher().closeConnection( connection ); } } } |
From: <hib...@li...> - 2006-07-13 03:31:29
|
Author: ste...@jb... Date: 2006-07-12 23:31:21 -0400 (Wed, 12 Jul 2006) New Revision: 10116 Added: branches/Hibernate_3_1_3_JBAS-3375/Hibernate3/ Log: copied v313 as base for patch Copied: branches/Hibernate_3_1_3_JBAS-3375/Hibernate3 (from rev 10115, tags/v313/Hibernate3) |
From: <hib...@li...> - 2006-07-13 03:29:11
|
Author: ste...@jb... Date: 2006-07-12 23:29:06 -0400 (Wed, 12 Jul 2006) New Revision: 10115 Added: branches/Hibernate_3_1_3_JBAS-3375/ Log: patch branch for JBAS-3375 |
From: <hib...@li...> - 2006-07-13 02:16:28
|
Author: epbernard Date: 2006-07-12 22:16:13 -0400 (Wed, 12 Jul 2006) New Revision: 10114 Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/FieldBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/LuceneSession.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/BridgeFactory.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DateBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DoubleBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FloatBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IntegerBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/LongBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/NumberBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/ParameterizedBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/Resolution.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringImplBridge.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/EntityInfo.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/IteratorImpl.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/LuceneQueryImpl.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/ScrollableResultsImpl.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/util/ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/util/BinderHelper.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/MappingTest.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/TestCase.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/query/ branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/query/Book.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/query/Clock.java branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/query/QueryTest.java Modified: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java Log: Prototype for Hibernate Lucene Query + field bridge Modified: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -1,7 +1,6 @@ //$Id$ package org.hibernate.lucene; -import java.beans.Introspector; import java.io.Serializable; import java.lang.reflect.AccessibleObject; import java.lang.reflect.AnnotatedElement; @@ -17,8 +16,13 @@ import org.apache.lucene.index.Term; import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; +import org.hibernate.util.ReflectHelper; import org.hibernate.cfg.annotations.Version; import org.hibernate.lucene.store.DirectoryProvider; +import org.hibernate.lucene.bridge.FieldBridge; +import org.hibernate.lucene.bridge.BridgeFactory; +import org.hibernate.lucene.util.BinderHelper; +import org.hibernate.lucene.event.LuceneEventListener; //TODO handle attribute (only getters are handled currently) public class DocumentBuilder<T> { @@ -39,6 +43,8 @@ private String idKeywordName; private final Analyzer analyzer; private Float idBoost; + public static final String CLASS_FIELDNAME = "_hibernate_class"; + private FieldBridge idBridge; public DocumentBuilder(Class<?> clazz, Analyzer analyzer, DirectoryProvider directory) { //this.beanClass = clazz; @@ -51,10 +57,11 @@ Method method = methods[i]; Keyword keywordAnn = method.getAnnotation( Keyword.class ); if ( keywordAnn != null ) { - String name = getAttributeName( method, keywordAnn.name() ); + String name = BinderHelper.getAttributeName( method, keywordAnn.name() ); if ( keywordAnn.id() ) { idKeywordName = name; idBoost = getBoost( method ); + idBridge = BridgeFactory.guessType( method ); } else { setAccessible( method ); @@ -66,12 +73,12 @@ if ( unstoredAnn != null ) { setAccessible( method ); unstoredGetters.add( method ); - unstoredNames.add( getAttributeName( method, unstoredAnn.name() ) ); + unstoredNames.add( BinderHelper.getAttributeName( method, unstoredAnn.name() ) ); } Text textAnn = method.getAnnotation( Text.class ); if ( textAnn != null ) { textGetters.add( method ); - textNames.add( getAttributeName( method, textAnn.name() ) ); + textNames.add( BinderHelper.getAttributeName( method, textAnn.name() ) ); } } } @@ -111,11 +118,9 @@ doc.setBoost( boost.floatValue() ); } { - Field idField = new Field( idKeywordName, id.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED ); - if (idBoost != null) { - idField.setBoost( idBoost.floatValue() ); - } - doc.add( idField ); + Field classField = new Field( CLASS_FIELDNAME, instance.getClass().getName(), Field.Store.YES, Field.Index.NO); + doc.add( classField ); + idBridge.set( idKeywordName, id, doc, Field.Store.YES, Field.Index.UN_TOKENIZED, idBoost ); } for ( int i = 0; i < keywordNames.size() ; i++ ) { Member member = keywordGetters.get( i ); @@ -161,19 +166,6 @@ return new Term( idKeywordName, id.toString() ); } - private static String getAttributeName(Method method, String name) { - if( ! "".equals( name ) ) return name; //explicit field name - - //decapitalize - String methodName = method.getName(); - //FIXME we probably should exclude methods not starting with "get" nor "is" - int startIndex = 3; - if( methodName.startsWith("is") ) { - startIndex = 2; - } - return Introspector.decapitalize( methodName.substring( startIndex ) ); - } - public DirectoryProvider getDirectoryProvider() { return directoryProvider; } @@ -187,4 +179,30 @@ ( (AccessibleObject) member ).setAccessible( true ); } } + + public FieldBridge getIdBridge() { + return idBridge; + } + + public String getIdKeywordName() { + return idKeywordName; + } + + public static Class getDocumentClass(Document document) { + String className = document.get( DocumentBuilder.CLASS_FIELDNAME ); + try { + return ReflectHelper.classForName( className ); + } + catch (ClassNotFoundException e) { + throw new HibernateException("Unable to load indexed class: " + className, e); + } + } + + public static Serializable getDocumentId(LuceneEventListener listener, Class clazz, Document document) { + DocumentBuilder builder = listener.getDocumentBuilders().get( clazz ); + if (builder == null) throw new HibernateException("No Lucene configuration set up for: " + clazz.getName() ); + Serializable id = (Serializable) builder.getIdBridge().get( builder.getIdKeywordName(), document ); + return id; + } + } Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/FieldBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/FieldBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/FieldBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,22 @@ +//$Id: $ +package org.hibernate.lucene; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Documented; + +import org.hibernate.annotations.Parameter; + +/** + * specifies a given field bridge implementation + * @author Emmanuel Bernard + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +@Documented +public @interface FieldBridge { + public Class impl() default void.class; + public Parameter[] params() default {}; +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/LuceneSession.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/LuceneSession.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/LuceneSession.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,408 @@ +//$Id: $ +package org.hibernate.lucene; + +import java.io.Serializable; +import java.sql.Connection; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.hibernate.CacheMode; +import org.hibernate.Criteria; +import org.hibernate.EntityMode; +import org.hibernate.Filter; +import org.hibernate.FlushMode; +import org.hibernate.HibernateException; +import org.hibernate.LockMode; +import org.hibernate.Query; +import org.hibernate.ReplicationMode; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.cfg.NotYetImplementedException; +import org.hibernate.engine.query.ParameterMetadata; +import org.hibernate.impl.SessionImpl; +import org.hibernate.lucene.query.LuceneQueryImpl; +import org.hibernate.stat.SessionStatistics; +import org.hibernate.type.Type; + +/** + * Lucene aware session that allows lucene query creations + * + * @author Emmanuel Bernard + */ +public class LuceneSession implements Session { + private final SessionImpl session; + + public LuceneSession(Session session) { + this.session = (SessionImpl) session; + } + + /** + * Execute a Lucene query and retrieve managed objects + * @param entities must be immutable for the lifetime of the query object + */ + public Query createLuceneQuery(org.apache.lucene.search.Query luceneQuery, Class... entities) { + return new LuceneQueryImpl( luceneQuery, entities, session, new ParameterMetadata(null, null) ); + } + + public void index(Object object) { + throw new NotYetImplementedException(""); + //TODO + //need to add elements in a queue kept at the Session level + //the queue will be processed by a Lucene(Auto)FlushEventListener + //note that we could keep this queue somewhere in the event listener in the mean time but that requires + // a synchronized hashmap holding this queue on a per session basis plus some session house keeping (yuk) + //an other solution would be to subclass SessionImpl instead of having this LuceneSession delecation model + // this is an open discussion + } + + public Query createSQLQuery(String sql, String returnAlias, Class returnClass) { + return session.createSQLQuery( sql, returnAlias, returnClass ); + } + + public Query createSQLQuery(String sql, String[] returnAliases, Class[] returnClasses) { + return session.createSQLQuery( sql, returnAliases, returnClasses ); + } + + public int delete(String query) throws HibernateException { + return session.delete( query ); + } + + public int delete(String query, Object value, Type type) throws HibernateException { + return session.delete( query, value, type ); + } + + public int delete(String query, Object[] values, Type[] types) throws HibernateException { + return session.delete( query, values, types ); + } + + public Collection filter(Object collection, String filter) throws HibernateException { + return session.filter( collection, filter ); + } + + public Collection filter(Object collection, String filter, Object value, Type type) throws HibernateException { + return session.filter( collection, filter, value, type ); + } + + public Collection filter(Object collection, String filter, Object[] values, Type[] types) throws HibernateException { + return session.filter( collection, filter, values, types ); + } + + public List find(String query) throws HibernateException { + return session.find( query ); + } + + public List find(String query, Object value, Type type) throws HibernateException { + return session.find( query, value, type ); + } + + public List find(String query, Object[] values, Type[] types) throws HibernateException { + return session.find( query, values, types ); + } + + public Iterator iterate(String query) throws HibernateException { + return session.iterate( query ); + } + + public Iterator iterate(String query, Object value, Type type) throws HibernateException { + return session.iterate( query, value, type ); + } + + public Iterator iterate(String query, Object[] values, Type[] types) throws HibernateException { + return session.iterate( query, values, types ); + } + + public void save(String entityName, Object object, Serializable id) throws HibernateException { + session.save( entityName, object, id ); + } + + public void save(Object object, Serializable id) throws HibernateException { + session.save( object, id ); + } + + public Object saveOrUpdateCopy(String entityName, Object object) throws HibernateException { + return session.saveOrUpdateCopy( entityName, object ); + } + + public Object saveOrUpdateCopy(String entityName, Object object, Serializable id) throws HibernateException { + return session.saveOrUpdateCopy( entityName, object, id ); + } + + public Object saveOrUpdateCopy(Object object) throws HibernateException { + return session.saveOrUpdateCopy( object ); + } + + public Object saveOrUpdateCopy(Object object, Serializable id) throws HibernateException { + return session.saveOrUpdateCopy( object, id ); + } + + public void update(String entityName, Object object, Serializable id) throws HibernateException { + session.update( entityName, object, id ); + } + + public void update(Object object, Serializable id) throws HibernateException { + session.update( object, id ); + } + + public Transaction beginTransaction() throws HibernateException { + return session.beginTransaction(); + } + + public void cancelQuery() throws HibernateException { + session.cancelQuery(); + } + + public void clear() { + session.clear(); + } + + public Connection close() throws HibernateException { + return session.close(); + } + + public Connection connection() throws HibernateException { + return session.connection(); + } + + public boolean contains(Object object) { + return session.contains( object ); + } + + public Criteria createCriteria(String entityName) { + return session.createCriteria( entityName ); + } + + public Criteria createCriteria(String entityName, String alias) { + return session.createCriteria( entityName, alias ); + } + + public Criteria createCriteria(Class persistentClass) { + return session.createCriteria( persistentClass ); + } + + public Criteria createCriteria(Class persistentClass, String alias) { + return session.createCriteria( persistentClass, alias ); + } + + public Query createFilter(Object collection, String queryString) throws HibernateException { + return session.createFilter( collection, queryString ); + } + + public Query createQuery(String queryString) throws HibernateException { + return session.createQuery( queryString ); + } + + public SQLQuery createSQLQuery(String queryString) throws HibernateException { + return session.createSQLQuery( queryString ); + } + + public void delete(String entityName, Object object) throws HibernateException { + session.delete( entityName, object ); + } + + public void delete(Object object) throws HibernateException { + session.delete( object ); + } + + public void disableFilter(String filterName) { + session.disableFilter( filterName ); + } + + public Connection disconnect() throws HibernateException { + return session.disconnect(); + } + + public Filter enableFilter(String filterName) { + return session.enableFilter( filterName ); + } + + public void evict(Object object) throws HibernateException { + session.evict( object ); + } + + public void flush() throws HibernateException { + session.flush(); + } + + public Object get(Class clazz, Serializable id) throws HibernateException { + return session.get( clazz, id ); + } + + public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException { + return session.get( clazz, id, lockMode ); + } + + public Object get(String entityName, Serializable id) throws HibernateException { + return session.get( entityName, id ); + } + + public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException { + return session.get( entityName, id, lockMode ); + } + + public CacheMode getCacheMode() { + return session.getCacheMode(); + } + + public LockMode getCurrentLockMode(Object object) throws HibernateException { + return session.getCurrentLockMode( object ); + } + + public Filter getEnabledFilter(String filterName) { + return session.getEnabledFilter( filterName ); + } + + public EntityMode getEntityMode() { + return session.getEntityMode(); + } + + public String getEntityName(Object object) throws HibernateException { + return session.getEntityName( object ); + } + + public FlushMode getFlushMode() { + return session.getFlushMode(); + } + + public Serializable getIdentifier(Object object) throws HibernateException { + return session.getIdentifier( object ); + } + + public Query getNamedQuery(String queryName) throws HibernateException { + return session.getNamedQuery( queryName ); + } + + public org.hibernate.Session getSession(EntityMode entityMode) { + return session.getSession( entityMode ); + } + + public SessionFactory getSessionFactory() { + return session.getSessionFactory(); + } + + public SessionStatistics getStatistics() { + return session.getStatistics(); + } + + public Transaction getTransaction() { + return session.getTransaction(); + } + + public boolean isConnected() { + return session.isConnected(); + } + + public boolean isDirty() throws HibernateException { + return session.isDirty(); + } + + public boolean isOpen() { + return session.isOpen(); + } + + public Object load(String entityName, Serializable id) throws HibernateException { + return session.load( entityName, id ); + } + + public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException { + return session.load( entityName, id, lockMode ); + } + + public void load(Object object, Serializable id) throws HibernateException { + session.load( object, id ); + } + + public Object load(Class theClass, Serializable id) throws HibernateException { + return session.load( theClass, id ); + } + + public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException { + return session.load( theClass, id, lockMode ); + } + + public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException { + session.lock( entityName, object, lockMode ); + } + + public void lock(Object object, LockMode lockMode) throws HibernateException { + session.lock( object, lockMode ); + } + + public Object merge(String entityName, Object object) throws HibernateException { + return session.merge( entityName, object ); + } + + public Object merge(Object object) throws HibernateException { + return session.merge( object ); + } + + public void persist(String entityName, Object object) throws HibernateException { + session.persist( entityName, object ); + } + + public void persist(Object object) throws HibernateException { + session.persist( object ); + } + + public void reconnect() throws HibernateException { + session.reconnect(); + } + + public void reconnect(Connection connection) throws HibernateException { + session.reconnect( connection ); + } + + public void refresh(Object object) throws HibernateException { + session.refresh( object ); + } + + public void refresh(Object object, LockMode lockMode) throws HibernateException { + session.refresh( object, lockMode ); + } + + public void replicate(String entityName, Object object, ReplicationMode replicationMode) throws HibernateException { + session.replicate( entityName, object, replicationMode ); + } + + public void replicate(Object object, ReplicationMode replicationMode) throws HibernateException { + session.replicate( object, replicationMode ); + } + + public Serializable save(String entityName, Object object) throws HibernateException { + return session.save( entityName, object ); + } + + public Serializable save(Object object) throws HibernateException { + return session.save( object ); + } + + public void saveOrUpdate(String entityName, Object object) throws HibernateException { + session.saveOrUpdate( entityName, object ); + } + + public void saveOrUpdate(Object object) throws HibernateException { + session.saveOrUpdate( object ); + } + + public void setCacheMode(CacheMode cacheMode) { + session.setCacheMode( cacheMode ); + } + + public void setFlushMode(FlushMode flushMode) { + session.setFlushMode( flushMode ); + } + + public void setReadOnly(Object entity, boolean readOnly) { + session.setReadOnly( entity, readOnly ); + } + + public void update(String entityName, Object object) throws HibernateException { + session.update( entityName, object ); + } + + public void update(Object object) throws HibernateException { + session.update( object ); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/BridgeFactory.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/BridgeFactory.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/BridgeFactory.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,99 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Member; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.annotations.Parameter; +import org.hibernate.lucene.util.BinderHelper; + +/** + * @author Emmanuel Bernard + */ +public class BridgeFactory { + private static Map<String, FieldBridge> builtInBridges = new HashMap<String, FieldBridge>(); + private BridgeFactory() {} + + public static final FieldBridge DOUBLE = new String2FieldBridgeAdaptor( new DoubleBridge() ); + + public static final FieldBridge FLOAT = new String2FieldBridgeAdaptor( new FloatBridge() ); + + public static final FieldBridge INTEGER = new String2FieldBridgeAdaptor( new IntegerBridge() ); + + public static final FieldBridge LONG = new String2FieldBridgeAdaptor( new LongBridge() ); + + public static final FieldBridge STRING = new String2FieldBridgeAdaptor( new StringImplBridge() ); + + public static final FieldBridge DATE_YEAR; + public static final FieldBridge DATE_MONTH; + public static final FieldBridge DATE_DAY; + public static final FieldBridge DATE_HOUR; + public static final FieldBridge DATE_MINUTE; + public static final FieldBridge DATE_SECOND; + public static final FieldBridge DATE_MILLISECOND; + + static { + builtInBridges.put( Double.class.getName(), DOUBLE ); + builtInBridges.put( Float.class.getName(), FLOAT ); + builtInBridges.put( Integer.class.getName(), INTEGER ); + builtInBridges.put( Long.class.getName(), LONG ); + builtInBridges.put( String.class.getName(), STRING ); + + DATE_YEAR = createDateBridge( Resolution.YEAR ); + DATE_MONTH = createDateBridge( Resolution.MONTH ); + DATE_DAY = createDateBridge( Resolution.DAY ); + DATE_HOUR = createDateBridge( Resolution.HOUR ); + DATE_MINUTE = createDateBridge( Resolution.MINUTE ); + DATE_SECOND = createDateBridge( Resolution.SECOND ); + DATE_MILLISECOND = createDateBridge( Resolution.MILLISECOND ); + builtInBridges.put( Date.class.getName(), DATE_MILLISECOND ); + } + + private static FieldBridge createDateBridge(Resolution resolution) { + DateBridge date; + Map params = new HashMap(1); + params.put( "resolution", resolution ); + date = new DateBridge(); + date.setParameterValues( params ); + return new String2FieldBridgeAdaptor( date ); + } + + public static FieldBridge guessType(Member member) { + FieldBridge bridge = null; + org.hibernate.lucene.FieldBridge bridgeAnn = ( (AnnotatedElement) member ).getAnnotation( org.hibernate.lucene.FieldBridge.class ); + if (bridgeAnn != null) { + Class impl = bridgeAnn.impl(); + try { + Object instance = impl.newInstance(); + if ( FieldBridge.class.isAssignableFrom( impl ) ) { + bridge = (FieldBridge) instance; + } + else if ( StringBridge.class.isAssignableFrom( impl ) ) { + bridge = new String2FieldBridgeAdaptor( (StringBridge) instance ); + } + if ( bridgeAnn.params().length > 0 && ParameterizedBridge.class.isAssignableFrom( impl ) ) { + Map params = new HashMap( bridgeAnn.params().length ); + for ( Parameter param : bridgeAnn.params() ) { + params.put( param.name(), param.value() ); + } + ( (ParameterizedBridge) instance ).setParameterValues( params ); + } + } + catch (Exception e) { + throw new HibernateException("Unable to instanciate FieldBridge for " + BinderHelper.getAttributeName(member), e ); + } + } + else { + //find in built-ins + Class<?> returnType = BinderHelper.getReturnType( member ); + bridge = builtInBridges.get( returnType.getName() ); + } + if (bridge == null) throw new HibernateException("Unable to guess FieldBridge for " + BinderHelper.getAttributeName(member) ); + return bridge; + } + +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DateBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DateBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DateBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,62 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +import java.text.ParseException; +import java.util.Date; +import java.util.Map; + +import org.apache.lucene.document.DateTools; +import org.hibernate.AssertionFailure; +import org.hibernate.HibernateException; + +/** + * @author Emmanuel Bernard + */ +public class DateBridge implements StringBridge, ParameterizedBridge { + //TODO don't depend on such a weak 3rd party API for a public API of ours + DateTools.Resolution resolution; + + public Object stringToObject(String stringValue) { + //usually does not make sense + try { + return DateTools.stringToDate( stringValue ); + } + catch (ParseException e) { + throw new HibernateException( "Unable to parse into date: " + stringValue, e ); + } + } + + public String objectToString(Object object) { + return DateTools.dateToString( (Date) object, resolution ); + } + + public void setParameterValues(Map parameters) { + Resolution hibResolution = (Resolution) parameters.get( "resolution" ); + switch ( hibResolution ) { + case YEAR: + resolution = DateTools.Resolution.YEAR; + break; + case MONTH: + resolution = DateTools.Resolution.MONTH; + break; + case DAY: + resolution = DateTools.Resolution.DAY; + break; + case HOUR: + resolution = DateTools.Resolution.HOUR; + break; + case MINUTE: + resolution = DateTools.Resolution.MINUTE; + break; + case SECOND: + resolution = DateTools.Resolution.SECOND; + break; + case MILLISECOND: + resolution = DateTools.Resolution.MILLISECOND; + break; + default: + throw new AssertionFailure( "Unknown Resolution: " + hibResolution ); + + } + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DoubleBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DoubleBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/DoubleBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,11 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public class DoubleBridge extends NumberBridge { + public Object stringToObject(String stringValue) { + return new Double(stringValue); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FieldBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,18 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; + +/** + * Link between a java property and a Lucene Document + * Usually a Java property will be linked to a Document Field + * + * @author Emmanuel Bernard + */ +//TODO should show Field or document? +//document is nice since I can save an object into several fields +public interface FieldBridge { + Object get(String name, Document document); + void set(String name, Object value, Document document, Field.Store store, Field.Index index, Float boost); +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FloatBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FloatBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/FloatBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,11 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public class FloatBridge extends NumberBridge { + public Object stringToObject(String stringValue) { + return new Float(stringValue); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IntegerBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IntegerBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/IntegerBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,11 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public class IntegerBridge extends NumberBridge { + public Object stringToObject(String stringValue) { + return new Integer(stringValue); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/LongBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/LongBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/LongBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,11 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public class LongBridge extends NumberBridge { + public Object stringToObject(String stringValue) { + return new Long(stringValue); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/NumberBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/NumberBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/NumberBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,11 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public abstract class NumberBridge implements StringBridge { + public String objectToString(Object object) { + return object.toString(); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/ParameterizedBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/ParameterizedBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/ParameterizedBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,13 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +import java.util.Map; + +/** + * Allow parameter injection to a given bridge + * + * @author Emmanuel Bernard + */ +public interface ParameterizedBridge { + void setParameterValues(Map parameters); +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/Resolution.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/Resolution.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/Resolution.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,17 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * Date indexing resolution + * + * @author Emmanuel Bernard + */ +public enum Resolution { + YEAR, + MONTH, + DAY, + HOUR, + MINUTE, + SECOND, + MILLISECOND +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/String2FieldBridgeAdaptor.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,31 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; + +/** + * Bridge to use a Java2String as a Java2Field + * + * @author Emmanuel Bernard + */ +public class String2FieldBridgeAdaptor implements FieldBridge { + + private StringBridge stringBridge; + + public String2FieldBridgeAdaptor(StringBridge stringBridge) { + this.stringBridge = stringBridge; + } + public Object get(String name, Document document) { + Field field = document.getField( name ); + return stringBridge.stringToObject( field.stringValue() ); + } + + public void set(String name, Object value, Document document, Field.Store store, Field.Index index, Float boost) { + Field field = new Field(name, stringBridge.objectToString( value ), store, index); + if (boost != null) field.setBoost( boost ); + document.add( field ); + } + + +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,20 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * Transform an object into a stirng representation and vice versa + * + * @author Emmanuel Bernard + */ +public interface StringBridge { + /** + * Convert the string representation to an object + * FIXME: This operation might not always be possible + */ + Object stringToObject(String stringValue); + + /** + * convert the object representation to a String + */ + String objectToString(Object object); +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringImplBridge.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringImplBridge.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/bridge/StringImplBridge.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,15 @@ +//$Id: $ +package org.hibernate.lucene.bridge; + +/** + * @author Emmanuel Bernard + */ +public class StringImplBridge implements StringBridge { + public Object stringToObject(String stringValue) { + return stringValue; + } + + public String objectToString(Object object) { + return (String) object; + } +} Modified: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -41,10 +41,17 @@ * @author Emmanuel Bernard * @author Mattias Arbin */ -//TODO takes care of synchronization and index concurrent index change +//TODO work on sharing the same indexWriters and readers across a single post operation... public class LuceneEventListener implements PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener, Initializable { + //FIXME keeping this here is a bad decision since you might want to search indexes wo maintain it + @Deprecated + public Map<Class, DocumentBuilder<Object>> getDocumentBuilders() { + return documentBuilders; + } + + private Map<Class, DocumentBuilder<Object>> documentBuilders = new HashMap<Class, DocumentBuilder<Object>>(); //** keep track of the index modifiers per file since 1 index modifier can be present at a time */ private Map<DirectoryProvider, Lock> indexLock = new HashMap<DirectoryProvider, Lock>(); Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/EntityInfo.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/EntityInfo.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/EntityInfo.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,12 @@ +//$Id: $ +package org.hibernate.lucene.query; + +import java.io.Serializable; + +/** + * @author Emmanuel Bernard + */ +class EntityInfo { + public Class clazz; + public Serializable id; +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/IteratorImpl.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/IteratorImpl.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/IteratorImpl.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,38 @@ +//$Id: $ +package org.hibernate.lucene.query; + +import java.util.Iterator; + +import org.hibernate.Session; + +/** + * @author Emmanuel Bernard + */ +public class IteratorImpl implements Iterator { + + private final EntityInfo[] entityInfos; + private final Session session; + private int index = 0; + private final int size; + + public IteratorImpl(EntityInfo[] entityInfos, Session session) { + this.entityInfos = entityInfos; + this.session = session; + this.size = entityInfos.length; + } + + public boolean hasNext() { + return index < size; + } + + public Object next() { + Object object = session.get( entityInfos[index].clazz, entityInfos[index].id ); + index++; + return object; + } + + public void remove() { + //TODO this is theorically doable + throw new UnsupportedOperationException( "Cannot remove from a lucene query interator" ); + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/LuceneQueryImpl.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/LuceneQueryImpl.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/LuceneQueryImpl.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,258 @@ +//$Id: $ +package org.hibernate.lucene.query; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.lucene.document.Document; +import org.apache.lucene.search.Hits; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MultiSearcher; +import org.apache.lucene.search.Searcher; +import org.apache.lucene.store.Directory; +import org.hibernate.Hibernate; +import org.hibernate.HibernateException; +import org.hibernate.LockMode; +import org.hibernate.Query; +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.engine.SessionImplementor; +import org.hibernate.engine.query.ParameterMetadata; +import org.hibernate.event.PostInsertEventListener; +import org.hibernate.impl.AbstractQueryImpl; +import org.hibernate.lucene.DocumentBuilder; +import org.hibernate.lucene.event.LuceneEventListener; + +/** + * @author Emmanuel Bernard + */ +//implements setParameter() +public class LuceneQueryImpl extends AbstractQueryImpl { + private static final Log log = LogFactory.getLog( LuceneQueryImpl.class ); + private org.apache.lucene.search.Query luceneQuery; + private Class[] classes; + private Integer firstResult; + private Integer maxResults; + private int resultSize; + + /** classes must be immutable */ + public LuceneQueryImpl(org.apache.lucene.search.Query query, Class[] classes, SessionImplementor session, ParameterMetadata parameterMetadata) { + //TODO handle flushMode + super( query.toString(), null, session, parameterMetadata ); + this.luceneQuery = query; + this.classes = classes; + } + + /** + * Return an interator on the results. + * Retrieve the object one by one (initialize it during the next() operation) + */ + public Iterator iterate() throws HibernateException { + //implement an interator which keep the id/class for each hit and get the object on demand + //cause I can't keep the searcher and hence the hit opened. I dont have any hook to know when the + //user stop using it + //scrollable is better in this area + + LuceneEventListener listener = getLuceneEventListener(); + //find the directories + Searcher searcher = buildSearcher( listener ); + Hits hits; + try { + hits = searcher.search( luceneQuery ); + setResultSize(hits); + int first = first(); + int max = max( first, hits ); + EntityInfo[] entityInfos = new EntityInfo[max - first + 1]; + for (int index = first ; index <= max ; index++ ) { + Document document = hits.doc( index ); + EntityInfo entityInfo = new EntityInfo(); + entityInfo.clazz = DocumentBuilder.getDocumentClass( document ); + //FIXME should check that clazz match classes but this complexify a lot the firstResult/maxResult + entityInfo.id = DocumentBuilder.getDocumentId( listener, entityInfo.clazz, document ); + entityInfos[ index - first ] = entityInfo; + } + return new IteratorImpl( entityInfos, (Session) this.session ); + } + catch (IOException e) { + throw new HibernateException("Unable to query Lucene index", e); + } + finally { + if (searcher != null) try { + searcher.close(); + } + catch (IOException e) { + log.warn( "Unable to properly close searcher during lucene query: " + getQueryString(), e ); + } + } + } + + public ScrollableResults scroll() throws HibernateException { + //keep the searcher open until the resultset is closed + LuceneEventListener listener = getLuceneEventListener(); + //find the directories + Searcher searcher = buildSearcher( listener ); + Hits hits; + try { + hits = searcher.search( luceneQuery ); + setResultSize(hits); + int first = first(); + int max = max( first, hits ); + return new ScrollableResultsImpl( searcher, hits, first, max, (Session) this.session, listener ); + } + catch (IOException e) { + try { + if ( searcher != null ) searcher.close(); + } + catch (IOException ee) { + //we have the initial issue already + } + throw new HibernateException("Unable to query Lucene index", e); + } + } + + public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException { + //TODO think about this scrollmode + return scroll(); + } + + public List list() throws HibernateException { + LuceneEventListener listener = getLuceneEventListener(); + //find the directories + Searcher searcher = buildSearcher( listener ); + Hits hits; + try { + hits = searcher.search( luceneQuery ); + setResultSize(hits); + int first = first(); + int max = max( first, hits ); + List result = new ArrayList( max - first + 1); + Session sess = (Session) this.session; + for (int index = first ; index <= max ; index++ ) { + Document document = hits.doc( index ); + Class clazz = DocumentBuilder.getDocumentClass( document ); + //FIXME should check that clazz match classes but this complexify a lot the firstResult/maxResult + Serializable id = DocumentBuilder.getDocumentId( listener, clazz, document ); + result.add( sess.load( clazz, id ) ); + //use load to benefit from the batch-size (but facing some proxy casting issues... + } + //then initialize the objects + for (Object element : result) { + Hibernate.initialize(element); + } + return result; + } + catch (IOException e) { + throw new HibernateException("Unable to query Lucene index", e); + } + finally { + if (searcher != null) try { + searcher.close(); + } + catch (IOException e) { + log.warn( "Unable to properly close searcher during lucene query: " + getQueryString(), e ); + } + } + } + + private int max(int first, Hits hits) { + return maxResults == null ? + first + hits.length() - 1 : + maxResults + first < hits.length() ? + first + maxResults : + hits.length() - 1; + } + + private int first() { + return firstResult != null ? firstResult : 0; + } + + private Searcher buildSearcher(LuceneEventListener listener) { + Map<Class, DocumentBuilder<Object>> builders = listener.getDocumentBuilders(); + Set<Directory> directories = new HashSet<Directory>(); + for (Class clazz : classes) { + DocumentBuilder builder = builders.get(clazz); + if (builder == null) throw new HibernateException( "Not a mapped entity: " + clazz); + directories.add( builder.getDirectoryProvider().getDirectory() ); + } + + //set up the searcher + Searcher searcher; + int dirNbr = directories.size(); + if (dirNbr > 1) { + try { + IndexSearcher[] searchers = new IndexSearcher[ dirNbr ]; + Iterator<Directory> it = directories.iterator(); + for (int index = 0 ; index < dirNbr ; index++) { + searchers[index] = new IndexSearcher( it.next() ); + } + searcher = new MultiSearcher(searchers); + } + catch(IOException e) { + throw new HibernateException("Unable to read Lucene directory", e); + } + } + else { + try { + searcher = new IndexSearcher( directories.iterator().next() ); + } + catch (IOException e) { + throw new HibernateException("Unable to read Lucene directory", e); + } + } + return searcher; + } + + private void setResultSize(Hits hits) { + resultSize = hits.length(); + } + + //FIXME does it make sense + public int resultSize() { + return this.resultSize; + } + + public Query setFirstResult(int firstResult) { + this.firstResult = firstResult; + return this; + } + + public Query setMaxResults(int maxResults) { + this.maxResults = maxResults; + return this; + } + + private LuceneEventListener getLuceneEventListener() { + PostInsertEventListener[] listeners = session.getListeners().getPostCommitInsertEventListeners(); + LuceneEventListener listener = null; + //FIXME this sucks since we mandante the event listener use + for(PostInsertEventListener candidate : listeners ) { + if (candidate instanceof LuceneEventListener) { + listener = (LuceneEventListener) candidate; + break; + } + } + if (listener == null) throw new HibernateException("Lucene event listener not initialized"); + return listener; + } + + public int executeUpdate() throws HibernateException { + throw new HibernateException( "Not supported operation" ); + } + + public Query setLockMode(String alias, LockMode lockMode) { + return null; + } + + protected Map getLockModes() { + return null; + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/ScrollableResultsImpl.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/ScrollableResultsImpl.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/query/ScrollableResultsImpl.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,217 @@ +//$Id: $ +package org.hibernate.lucene.query; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Blob; +import java.sql.Clob; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.lucene.document.Document; +import org.apache.lucene.search.Hits; +import org.apache.lucene.search.Searcher; +import org.hibernate.HibernateException; +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.lucene.DocumentBuilder; +import org.hibernate.lucene.event.LuceneEventListener; +import org.hibernate.type.Type; + +/** + * @author Emmanuel Bernard + */ +public class ScrollableResultsImpl implements ScrollableResults { + private final Searcher searcher; + private final Hits hits; + private final int first; + private final int max; + private int current; + private final Session session; + private final LuceneEventListener listener; + private EntityInfo[] entityInfos; + + public ScrollableResultsImpl( + Searcher searcher, Hits hits, int first, int max, Session session, LuceneEventListener listener + ) { + this.searcher = searcher; + this.hits = hits; + this.first = first; + this.max = max; + this.current = first; + this.session = session; + this.listener = listener; + entityInfos = new EntityInfo[max - first + 1]; + } + public boolean next() throws HibernateException { + return ++current <= max; + } + + public boolean previous() throws HibernateException { + return --current >= first; + } + + public boolean scroll(int i) throws HibernateException { + current = current + i; + return current >= first && current <= max; + } + + public boolean last() throws HibernateException { + current = max; + return max >= first; + } + + public boolean first() throws HibernateException { + current = first; + return max >= first; + } + + public void beforeFirst() throws HibernateException { + current = first - 1; + } + + public void afterLast() throws HibernateException { + current = max + 1; + } + + public boolean isFirst() throws HibernateException { + return current == first; + } + + public boolean isLast() throws HibernateException { + return current == max; + } + + public void close() throws HibernateException { + try { + searcher.close(); + } + catch (IOException e) { + throw new HibernateException( "Unable to close Lucene searcher", e); + } + } + + public Object[] get() throws HibernateException { + if (current < first || current > max) return null; //or exception? + EntityInfo info = entityInfos[current - first]; + if ( info == null ) { + info = new EntityInfo(); + Document document = null; + try { + document = hits.doc( current ); + } + catch (IOException e) { + throw new HibernateException( "Unable to read Lucene hits[" + current + "]", e); + } + info.clazz = DocumentBuilder.getDocumentClass( document ); + //FIXME should check that clazz match classes but this complexify a lot the firstResult/maxResult + info.id = DocumentBuilder.getDocumentId( listener, info.clazz, document ); + entityInfos[current - first] = info; + } + return new Object[] { + session.get( info.clazz, info.id ) + }; + } + + public Object get(int i) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Type getType(int i) { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Integer getInteger(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Long getLong(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Float getFloat(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Boolean getBoolean(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Double getDouble(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Short getShort(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Byte getByte(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Character getCharacter(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public byte[] getBinary(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public String getText(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Blob getBlob(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Clob getClob(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public String getString(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public BigDecimal getBigDecimal(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public BigInteger getBigInteger(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Date getDate(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Locale getLocale(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public Calendar getCalendar(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public TimeZone getTimeZone(int col) throws HibernateException { + throw new UnsupportedOperationException( "Lucene does not work on columns" ); + } + + public int getRowNumber() throws HibernateException { + if ( max < first ) return -1; + return current - first; + } + + public boolean setRowNumber(int rowNumber) throws HibernateException { + if (rowNumber >= 0) { + current = first + rowNumber; + } + else { + current = max + rowNumber + 1; //max row start at -1 + } + return current >= first && current <= max; + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/util/BinderHelper.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/util/BinderHelper.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/java/org/hibernate/lucene/util/BinderHelper.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,51 @@ +//$Id: $ +package org.hibernate.lucene.util; + +import java.lang.reflect.Method; +import java.lang.reflect.Member; +import java.lang.reflect.Field; +import java.beans.Introspector; + +import org.hibernate.util.StringHelper; + +/** + * @author Emmanuel Bernard + */ +public abstract class BinderHelper { + + private BinderHelper() {} + + public static String getAttributeName(Member member) { + return getAttributeName( member, null ); + } + /** + * Get attribute name out of member unless overriden by <code>name</code> + */ + //TODO move to reflection layer + public static String getAttributeName(Member member, String name) { + if( StringHelper.isNotEmpty( name ) ) return name; //explicit field name + if (member instanceof Field ) { + return ( (Field) member ).getName(); + } + else { + //decapitalize + String methodName = ( (Method) member).getName(); + //FIXME we probably should exclude methods not starting with "get" nor "is" + int startIndex = 3; + if( methodName.startsWith("is") ) { + startIndex = 2; + } + return Introspector.decapitalize( methodName.substring( startIndex ) ); + } + } + + //TODO move to reflection layer + public static Class<?> getReturnType(Member member) { + if (member instanceof Field) { + return ( (Field) member ).getType(); + } + else { + return ( (Method) member ).getReturnType(); + } + } +} Added: branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java =================================================================== --- branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java 2006-07-13 01:52:08 UTC (rev 10113) +++ branches/Lucene_Integration/HibernateExt/metadata/src/test/org/hibernate/lucene/test/Document.java 2006-07-13 02:16:13 UTC (rev 10114) @@ -0,0 +1,72 @@ +//$Id: Document.java 10014 2006-06-12 09:56:27 -0700 (lun., 12 juin 2006) epbernard $ +package org.hibernate.lucene.test; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Lob; + +import org.hibernate.lu... [truncated message content] |