[hibernate-commits] Hibernate SVN: r11260 - in branches/Branch_3_2/HibernateExt/search/src: java/org/hibernate/search/engine and 2 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Wed Mar 7 18:02:51 EST 2007
Author: epbernard
Date: 2007-03-07 18:02:51 -0500 (Wed, 07 Mar 2007)
New Revision: 11260
Added:
branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/IndexedEmbedded.java
branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/
branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java
branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Owner.java
branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Tower.java
Modified:
branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
Log:
HSEARCH-27
Added: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/IndexedEmbedded.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/IndexedEmbedded.java (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/annotations/IndexedEmbedded.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -0,0 +1,31 @@
+//$Id: $
+package org.hibernate.search.annotations;
+
+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;
+
+ at Retention( RetentionPolicy.RUNTIME )
+ at Target( { ElementType.FIELD, ElementType.METHOD } )
+ at Documented
+/**
+ * Specifies that an association (@*ToOne or @Embedded) is to be indexed
+ * in the root entity index
+ * It allows queries involving associated objects restrictions
+ */
+public @interface IndexedEmbedded {
+ /**
+ * Field name prefix
+ * Default to 'propertyname.'
+ */
+ String prefix() default ".";
+
+ /**
+ * Stop indexing embedded elements when depth is reached
+ * depth=1 means the associated element is index, but not its embedded elements
+ * Default: infinite (an exception will be raised in case of class circular reference when infinite is chosen)
+ */
+ int depth() default Integer.MAX_VALUE;
+}
Modified: branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java 2007-03-07 22:55:12 UTC (rev 11259)
+++ branches/Branch_3_2/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -8,11 +8,16 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.HashMap;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.Term;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass;
@@ -28,12 +33,14 @@
import org.hibernate.search.annotations.Store;
import org.hibernate.search.annotations.Text;
import org.hibernate.search.annotations.Unstored;
+import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.bridge.BridgeFactory;
import org.hibernate.search.bridge.FieldBridge;
import org.hibernate.search.bridge.TwoWayFieldBridge;
import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.util.BinderHelper;
import org.hibernate.util.ReflectHelper;
+import org.hibernate.Hibernate;
/**
* Set up and provide a manager for indexes classes
@@ -44,21 +51,9 @@
* @author Richard Hallier
*/
public class DocumentBuilder<T> {
- private final List<XMember> keywordGetters = new ArrayList<XMember>();
- private final List<String> keywordNames = new ArrayList<String>();
- private final List<FieldBridge> keywordBridges = new ArrayList<FieldBridge>();
- private final List<XMember> unstoredGetters = new ArrayList<XMember>();
- private final List<String> unstoredNames = new ArrayList<String>();
- private final List<FieldBridge> unstoredBridges = new ArrayList<FieldBridge>();
- private final List<XMember> textGetters = new ArrayList<XMember>();
- private final List<String> textNames = new ArrayList<String>();
- private final List<FieldBridge> textBridges = new ArrayList<FieldBridge>();
- private final List<String> fieldNames = new ArrayList<String>();
- private final List<XMember> fieldGetters = new ArrayList<XMember>();
- private final List<FieldBridge> fieldBridges = new ArrayList<FieldBridge>();
- private final List<Field.Store> fieldStore = new ArrayList<Field.Store>();
- private final List<Field.Index> fieldIndex = new ArrayList<Field.Index>();
+ private static final Log log = LogFactory.getLog( DocumentBuilder.class );
+ private final PropertiesMetadata rootPropertiesMetadata = new PropertiesMetadata();
private final XClass beanClass;
private final DirectoryProvider directoryProvider;
private String idKeywordName;
@@ -68,6 +63,8 @@
private TwoWayFieldBridge idBridge;
private Set<Class> mappedSubclasses = new HashSet<Class>();
private ReflectionManager reflectionManager;
+ private int level = 0;
+ private int maxLevel = Integer.MAX_VALUE;
public DocumentBuilder(XClass clazz, Analyzer analyzer, DirectoryProvider directory,
@@ -78,31 +75,41 @@
//FIXME get rid of it when boost is stored?
this.reflectionManager = reflectionManager;
- if ( clazz == null ) throw new AssertionFailure( "Unable to build a DocumentBuilder with a null class" );
+ if ( clazz == null ) throw new AssertionFailure( "Unable to build a DocumemntBuilder with a null class" );
- for ( XClass currClass = beanClass; currClass != null; currClass = currClass.getSuperclass() ) {
+ rootPropertiesMetadata.boost = getBoost( clazz );
+ Set<XClass> processedClasses = new HashSet<XClass>();
+ processedClasses.add( clazz );
+ initializeMembers(clazz, rootPropertiesMetadata, true, "", processedClasses );
+ //processedClasses.remove( clazz ); for the sake of completness
+
+ if ( idKeywordName == null ) {
+ throw new SearchException( "No document id for: " + clazz.getName() );
+ }
+ }
+
+ private void initializeMembers(XClass clazz, PropertiesMetadata propertiesMetadata, boolean isRoot, String prefix,
+ Set<XClass> processedClasses) {
+ for ( XClass currClass = clazz; currClass != null; currClass = currClass.getSuperclass() ) {
//rejecting non properties because the object is loaded from Hibernate, so indexing a non property does not make sense
List<XProperty> methods = currClass.getDeclaredProperties( XClass.ACCESS_PROPERTY );
for ( XProperty method : methods ) {
- initializeMember( method );
+ initializeMember( method, propertiesMetadata, isRoot, prefix, processedClasses );
}
List<XProperty> fields = currClass.getDeclaredProperties( XClass.ACCESS_FIELD );
for ( XProperty field : fields ) {
- initializeMember( field );
+ initializeMember( field, propertiesMetadata, isRoot, prefix, processedClasses );
}
}
-
- if ( idKeywordName == null ) {
- throw new SearchException( "No document id for: " + clazz.getName() );
- }
}
- private void initializeMember(XProperty member) {
+ private void initializeMember(XProperty member, PropertiesMetadata propertiesMetadata, boolean isRoot,
+ String prefix, Set<XClass> processedClasses) {
Keyword keywordAnn = member.getAnnotation( Keyword.class );
if ( keywordAnn != null ) {
- String name = BinderHelper.getAttributeName( member, keywordAnn.name() );
- if ( keywordAnn.id() ) {
+ String name = prefix + BinderHelper.getAttributeName( member, keywordAnn.name() );
+ if ( isRoot && keywordAnn.id() ) {
idKeywordName = name;
idBoost = getBoost( member );
FieldBridge fieldBridge = BridgeFactory.guessType( member );
@@ -116,35 +123,35 @@
}
else {
setAccessible( member );
- keywordGetters.add( member );
- keywordNames.add( name );
- keywordBridges.add( BridgeFactory.guessType( member ) );
+ propertiesMetadata.keywordGetters.add( member );
+ propertiesMetadata.keywordNames.add( name );
+ propertiesMetadata.keywordBridges.add( BridgeFactory.guessType( member ) );
}
}
Unstored unstoredAnn = member.getAnnotation( Unstored.class );
if ( unstoredAnn != null ) {
setAccessible( member );
- unstoredGetters.add( member );
- unstoredNames.add( BinderHelper.getAttributeName( member, unstoredAnn.name() ) );
- unstoredBridges.add( BridgeFactory.guessType( member ) );
+ propertiesMetadata.unstoredGetters.add( member );
+ propertiesMetadata.unstoredNames.add( prefix + BinderHelper.getAttributeName( member, unstoredAnn.name() ) );
+ propertiesMetadata.unstoredBridges.add( BridgeFactory.guessType( member ) );
}
Text textAnn = member.getAnnotation( Text.class );
if ( textAnn != null ) {
setAccessible( member );
- textGetters.add( member );
- textNames.add( BinderHelper.getAttributeName( member, textAnn.name() ) );
- textBridges.add( BridgeFactory.guessType( member ) );
+ propertiesMetadata.textGetters.add( member );
+ propertiesMetadata.textNames.add( prefix + BinderHelper.getAttributeName( member, textAnn.name() ) );
+ propertiesMetadata.textBridges.add( BridgeFactory.guessType( member ) );
}
DocumentId documentIdAnn = member.getAnnotation( DocumentId.class );
- if ( documentIdAnn != null ) {
+ if ( isRoot && documentIdAnn != null ) {
if ( idKeywordName != null ) {
throw new AssertionFailure( "Two document id assigned: "
+ idKeywordName + " and " + BinderHelper.getAttributeName( member, documentIdAnn.name() ) );
}
- idKeywordName = BinderHelper.getAttributeName( member, documentIdAnn.name() );
+ idKeywordName = prefix + BinderHelper.getAttributeName( member, documentIdAnn.name() );
FieldBridge fieldBridge = BridgeFactory.guessType( member );
if ( fieldBridge instanceof TwoWayFieldBridge ) {
idBridge = (TwoWayFieldBridge) fieldBridge;
@@ -160,14 +167,63 @@
member.getAnnotation( org.hibernate.search.annotations.Field.class );
if ( fieldAnn != null ) {
setAccessible( member );
- fieldGetters.add( member );
- fieldNames.add( BinderHelper.getAttributeName( member, fieldAnn.name() ) );
- fieldStore.add( getStore( fieldAnn.store() ) );
- fieldIndex.add( getIndex( fieldAnn.index() ) );
- fieldBridges.add( BridgeFactory.guessType( member ) );
+ propertiesMetadata.fieldGetters.add( member );
+ propertiesMetadata.fieldNames.add( prefix + BinderHelper.getAttributeName( member, fieldAnn.name() ) );
+ propertiesMetadata.fieldStore.add( getStore( fieldAnn.store() ) );
+ propertiesMetadata.fieldIndex.add( getIndex( fieldAnn.index() ) );
+ propertiesMetadata.fieldBridges.add( BridgeFactory.guessType( member ) );
}
+
+ IndexedEmbedded embeddedAnn = member.getAnnotation( IndexedEmbedded.class );
+ if ( embeddedAnn != null ) {
+ int oldMaxLevel = maxLevel;
+ maxLevel = embeddedAnn.depth() + level > maxLevel ? maxLevel : embeddedAnn.depth() + level;
+ level++;
+
+ if ( maxLevel == Integer.MAX_VALUE //infinite
+ && processedClasses.contains( member.getClassOrElementClass() ) ) {
+ throw new SearchException(
+ "Circular reference. Duplicate use of "
+ + member.getClassOrElementClass().getName()
+ + " in root entity " + beanClass.getName()
+ + "#" + buildEmbeddedPrefix( prefix, embeddedAnn, member )
+ );
+ }
+ if (level <= maxLevel) {
+ processedClasses.add( member.getClassOrElementClass() ); //push
+
+ setAccessible( member );
+ propertiesMetadata.embeddedGetters.add( member );
+ PropertiesMetadata metadata = new PropertiesMetadata();
+ propertiesMetadata.embeddedPropertiesMetadata.add(metadata);
+ metadata.boost = getBoost( member );
+ String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
+ initializeMembers( member.getClassOrElementClass(), metadata, false, localPrefix, processedClasses);
+
+ processedClasses.remove( member.getClassOrElementClass() ); //pop
+ }
+ else if ( log.isTraceEnabled() ) {
+ String localPrefix = buildEmbeddedPrefix( prefix, embeddedAnn, member );
+ log.trace( "depth reached, ignoring " + localPrefix );
+ }
+
+ level--;
+ maxLevel = oldMaxLevel; //set back the the old max level
+ }
}
+ private String buildEmbeddedPrefix(String prefix, IndexedEmbedded embeddedAnn, XProperty member) {
+ String localPrefix = prefix;
+ if ( ".".equals( embeddedAnn.prefix() ) ) {
+ //default to property name
+ localPrefix += member.getName() + '.';
+ }
+ else {
+ localPrefix += embeddedAnn.prefix();
+ }
+ return localPrefix;
+ }
+
private Field.Store getStore(Store store) {
switch (store) {
case NO:
@@ -204,7 +260,7 @@
null;
}
- private Object getMemberValue(T bean, XMember getter) {
+ private Object getMemberValue(Object bean, XMember getter) {
Object value;
try {
value = getter.invoke( bean );
@@ -218,9 +274,8 @@
public Document getDocument(T instance, Serializable id) {
Document doc = new Document();
XClass instanceClass = reflectionManager.toXClass( instance.getClass() );
- Float boost = getBoost( instanceClass );
- if ( boost != null ) {
- doc.setBoost( boost );
+ if ( rootPropertiesMetadata.boost != null ) {
+ doc.setBoost( rootPropertiesMetadata.boost );
}
{
Field classField =
@@ -228,39 +283,52 @@
doc.add( classField );
idBridge.set( idKeywordName, id, doc, Field.Store.YES, Field.Index.UN_TOKENIZED, idBoost );
}
- for ( int i = 0; i < keywordNames.size(); i++ ) {
- XMember member = keywordGetters.get( i );
+ buildDocumentFields( instance, doc, rootPropertiesMetadata );
+ return doc;
+ }
+
+ private void buildDocumentFields(Object instance, Document doc, PropertiesMetadata propertiesMetadata) {
+ if (instance == null) return;
+
+ for ( int i = 0; i < propertiesMetadata.keywordNames.size(); i++ ) {
+ XMember member = propertiesMetadata.keywordGetters.get( i );
Object value = getMemberValue( instance, member );
- keywordBridges.get( i ).set(
- keywordNames.get( i ), value, doc, Field.Store.YES,
+ propertiesMetadata.keywordBridges.get( i ).set(
+ propertiesMetadata.keywordNames.get( i ), value, doc, Field.Store.YES,
Field.Index.UN_TOKENIZED, getBoost( member )
);
}
- for ( int i = 0; i < textNames.size(); i++ ) {
- XMember member = textGetters.get( i );
+ for ( int i = 0; i < propertiesMetadata.textNames.size(); i++ ) {
+ XMember member = propertiesMetadata.textGetters.get( i );
Object value = getMemberValue( instance, member );
- textBridges.get( i ).set(
- textNames.get( i ), value, doc, Field.Store.YES,
+ propertiesMetadata.textBridges.get( i ).set(
+ propertiesMetadata.textNames.get( i ), value, doc, Field.Store.YES,
Field.Index.TOKENIZED, getBoost( member )
);
}
- for ( int i = 0; i < unstoredNames.size(); i++ ) {
- XMember member = unstoredGetters.get( i );
+ for ( int i = 0; i < propertiesMetadata.unstoredNames.size(); i++ ) {
+ XMember member = propertiesMetadata.unstoredGetters.get( i );
Object value = getMemberValue( instance, member );
- unstoredBridges.get( i ).set(
- unstoredNames.get( i ), value, doc, Field.Store.NO,
+ propertiesMetadata.unstoredBridges.get( i ).set(
+ propertiesMetadata.unstoredNames.get( i ), value, doc, Field.Store.NO,
Field.Index.TOKENIZED, getBoost( member )
);
}
- for ( int i = 0; i < fieldNames.size(); i++ ) {
- XMember member = fieldGetters.get( i );
+ for ( int i = 0; i < propertiesMetadata.fieldNames.size(); i++ ) {
+ XMember member = propertiesMetadata.fieldGetters.get( i );
Object value = getMemberValue( instance, member );
- fieldBridges.get( i ).set(
- fieldNames.get( i ), value, doc, fieldStore.get( i ),
- fieldIndex.get( i ), getBoost( member )
+ propertiesMetadata.fieldBridges.get( i ).set(
+ propertiesMetadata.fieldNames.get( i ), value, doc, propertiesMetadata.fieldStore.get( i ),
+ propertiesMetadata.fieldIndex.get( i ), getBoost( member )
);
}
- return doc;
+ for ( int i = 0; i < propertiesMetadata.embeddedGetters.size(); i++ ) {
+ XMember member = propertiesMetadata.embeddedGetters.get( i );
+ Object value = getMemberValue( instance, member );
+ //if ( ! Hibernate.isInitialized( value ) ) continue; //this sounds like a bad idea
+ //TODO handle boost at embedded level: already stored in propertiesMedatada.boost
+ buildDocumentFields( value, doc, propertiesMetadata.embeddedPropertiesMetadata.get( i ) );
+ }
}
public Term getTerm(Serializable id) {
@@ -320,4 +388,24 @@
public Set<Class> getMappedSubclasses() {
return mappedSubclasses;
}
+
+ private static class PropertiesMetadata {
+ public Float boost = null;
+ public final List<XMember> keywordGetters = new ArrayList<XMember>();
+ public final List<String> keywordNames = new ArrayList<String>();
+ public final List<FieldBridge> keywordBridges = new ArrayList<FieldBridge>();
+ public final List<XMember> unstoredGetters = new ArrayList<XMember>();
+ public final List<String> unstoredNames = new ArrayList<String>();
+ public final List<FieldBridge> unstoredBridges = new ArrayList<FieldBridge>();
+ public final List<XMember> textGetters = new ArrayList<XMember>();
+ public final List<String> textNames = new ArrayList<String>();
+ public final List<FieldBridge> textBridges = new ArrayList<FieldBridge>();
+ public final List<String> fieldNames = new ArrayList<String>();
+ public final List<XMember> fieldGetters = new ArrayList<XMember>();
+ public final List<FieldBridge> fieldBridges = new ArrayList<FieldBridge>();
+ public final List<Field.Store> fieldStore = new ArrayList<Field.Store>();
+ public final List<Field.Index> fieldIndex = new ArrayList<Field.Index>();
+ public final List<XMember> embeddedGetters = new ArrayList<XMember>();
+ public final List<PropertiesMetadata> embeddedPropertiesMetadata = new ArrayList<PropertiesMetadata>();
+ }
}
Added: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Address.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -0,0 +1,69 @@
+//$Id: $
+package org.hibernate.search.test.embedded;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.OneToOne;
+
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.DocumentId;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Emmanuel Bernard
+ */
+
+ at Entity
+ at Indexed
+public class Address {
+ @Id
+ @GeneratedValue
+ @DocumentId
+ private Long id;
+
+ @Field(index= Index.TOKENIZED)
+ private String street;
+
+ @IndexedEmbedded(depth = 1, prefix = "ownedBy_")
+ private Owner ownedBy;
+
+ @OneToOne(mappedBy = "address")
+ private Tower tower;
+
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public Owner getOwnedBy() {
+ return ownedBy;
+ }
+
+ public void setOwnedBy(Owner ownedBy) {
+ this.ownedBy = ownedBy;
+ }
+
+
+ public Tower getTower() {
+ return tower;
+ }
+
+ public void setTower(Tower tower) {
+ this.tower = tower;
+ }
+}
Added: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/EmbeddedTest.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -0,0 +1,63 @@
+//$Id: $
+package org.hibernate.search.test.embedded;
+
+import java.util.List;
+
+import org.hibernate.search.test.SearchTestCase;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.search.Query;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class EmbeddedTest extends SearchTestCase {
+
+ public void testEmbeddedIndexing() throws Exception {
+ Tower tower = new Tower();
+ tower.setName( "JBoss tower" );
+ Address a = new Address();
+ a.setStreet( "Tower place");
+ a.setTower( tower );
+ tower.setAddress( a );
+ Owner o = new Owner();
+ o.setName( "Atlanta Renting corp" );
+ a.setOwnedBy( o );
+ o.setAddress( a );
+
+ Session s = openSession( );
+ Transaction tx = s.beginTransaction();
+ s.persist( tower );
+ tx.commit();
+
+ s.clear();
+
+
+ FullTextSession session = Search.createFullTextSession(s);
+ QueryParser parser = new QueryParser("id", new StandardAnalyzer() );
+ Query query;
+ List result;
+
+ query = parser.parse("address.street:place");
+ result = session.createFullTextQuery(query).list();
+ assertEquals( "unable to find property in embedded", 1, result.size() );
+
+ query = parser.parse("address.ownedBy_name:renting");
+ result = session.createFullTextQuery(query, Tower.class).list();
+ assertEquals( "unable to find property in embedded", 1, result.size() );
+
+ s.close();
+
+ }
+
+ protected Class[] getMappings() {
+ return new Class[] {
+ Tower.class,
+ Address.class
+ };
+ }
+}
Added: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Owner.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Owner.java (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Owner.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -0,0 +1,39 @@
+//$Id: $
+package org.hibernate.search.test.embedded;
+
+import javax.persistence.Embeddable;
+
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.annotations.Parent;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Embeddable
+public class Owner {
+ @Field(index = Index.TOKENIZED)
+ private String name;
+
+ @Parent
+ @IndexedEmbedded //play the lunatic user
+ private Address address;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+}
Added: branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Tower.java
===================================================================
--- branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Tower.java (rev 0)
+++ branches/Branch_3_2/HibernateExt/search/src/test/org/hibernate/search/test/embedded/Tower.java 2007-03-07 23:02:51 UTC (rev 11260)
@@ -0,0 +1,58 @@
+//$Id: $
+package org.hibernate.search.test.embedded;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+import org.hibernate.search.annotations.DocumentId;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at Indexed
+public class Tower {
+ @Id
+ @GeneratedValue
+ @DocumentId
+ private Long id;
+
+ @Field( index = Index.TOKENIZED )
+ private String name;
+
+ @OneToOne( cascade = CascadeType.PERSIST )
+ @IndexedEmbedded
+ private Address address;
+
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+}
More information about the hibernate-commits
mailing list