-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: declaring Hibernate Annotation
PostPosted: Sun May 04, 2008 7:01 pm 
Beginner
Beginner

Joined: Mon Aug 13, 2007 2:37 am
Posts: 22
I'm trying to use Hibernate Annotation for Hibernate Search and I'm stuck. I'm trying to link the relationship between these 3 tables: Business, Business_Address, and Address.

Here's my table hbm.xml:
Code:
   
<hibernate-mapping>
    <class name="com.RXCoreApp.datamodel.BusinessCbo" table="Busines" schema="dbo" catalog="RX">
        <id name="businessId" type="java.lang.Integer">
            <column name="Business_Id" />
            <generator class="identity"></generator>
        </id>
        <property name="businessName" type="java.lang.String">
            <column name="Business_Name" />
        </property>
        <set name="businessAddresses" inverse="true" cascade="all-delete-orphan">
            <key>
                <column name="Business_Id" />
            </key>
            <one-to-many class="com.RXCoreApp.datamodel.BusinessAddressCbo" />
        </set>
    </class>
</hibernate-mapping>


Code:
   
<hibernate-mapping>
    <class name="com.RXCoreApp.datamodel.BusinessAddressCbo" table="Business_Address" schema="dbo" catalog="RX">
        <id name="businessAddressId" type="java.lang.Integer">
            <column name="Business_Address_Id" />
            <generator class="identity" />
        </id>
        <many-to-one name="address" class="com.RXCoreApp.datamodel.AddressCbo" fetch="select">
            <column name="Address_Id" />
        </many-to-one>
        <many-to-one name="busines" class="com.RXCoreApp.datamodel.BusinessCbo" fetch="select">
            <column name="Business_Id" />
        </many-to-one>
        <many-to-one name="addressType" class="com.RXCoreApp.datamodel.AddressTypeCbo" fetch="select">
            <column name="Address_Type_Id" />
        </many-to-one>
    </class>
</hibernate-mapping>


Code:
   
<hibernate-mapping>
    <class name="com.RXCoreApp.datamodel.AddressCbo" table="Address" schema="dbo" catalog="RX">
        <id name="addressId" type="java.lang.Integer">
            <column name="Address_Id" />
            <generator class="identity"></generator>
        </id>

        ...

        <set name="businessAddresses" inverse="true" cascade="all-delete-orphan">
            <key>
                <column name="Address_Id" />
            </key>
            <one-to-many class="com.RXCoreApp.datamodel.BusinessAddressCbo" />
        </set>
    </class>
</hibernate-mapping>


Here's my Annotation class:
Code:
   
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name = "Busines")
@Indexed(index="indexes/businesses")
public abstract class AbstractBusinessCbo  implements java.io.Serializable {


    // Fields   
   @Id
   @DocumentId
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "BUSINESS_ID", nullable = false)
     private Integer businessId;

     @OneToMany
     @JoinColumn (name = "BUSINESS_ID")
     private Set businessAddresses = new HashSet(0);

     ...


Code:
   
public abstract class AbstractBusinessAddress  implements java.io.Serializable {


    // Fields   

     private Integer businessAddressId;
     private AddressCbo address;
     private BusinessCbo busines;
...



Code:
   
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name = "Address")
@Indexed(index="indexes/addresses")
public abstract class AbstractAddressCbo  implements java.io.Serializable {

   @Id
   @DocumentId
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "ADDRESS_ID", nullable = false)
     private Integer addressId;

     private Set businessAddresses = new HashSet(0);
...


Here's my FULLTEXT search:
Code:
   
                  FullTextSession fullTextSession = Search.createFullTextSession( session );
                  MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[]{
                  "businessName", "businessAddresses.address.cityName", "businessAddresses.address.state"}, new StandardAnalyzer());
                  org.apache.lucene.search.Query query = parser.parse(searchString);
                  searchQry = fullTextSession.createFullTextQuery(query, BusinessCbo.class);
               countQry = searchQry;
               result = paginator.getPaginatdResult(session,countQry,searchQry,paginationControl_);



Can someone show me how to declare the join relationship using Annotation?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 07, 2008 5:41 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I am not quite sure what you are asking here. Here are some hints which might or might not help you ;-)

If you just want to map BusinessCbo to AddressCbo you should look at the @JoinTable annotation. However, it seems that your intermediate table contains more information than just the ids Business and Address. In this case you have to map the intermediate table as an entity. Something like this:
Code:
@Entity
@Table(name = "Business_Address")
public class BusinessAddress  {

    @Embeddable
    public static class Id implements Serializable {

       @Column(name = "Business_Id")
       private Integer businessId;

       @Column(name = "Address_Id")
       private Integer addressId;

      public Id() {}

      public Id( Integer businessId, Integer addressId) {

         this businessId = businessId;
         this addressId = addressId;
      }

      // implement equals() and hashCode() here
    }

    @EmbeddedId
    private Id id = new Id();

    private  AddressType type;

    @ManyToOne
    @JoinColumn(name="Business_Id", insertable = false, updatable = false)
    private Business business;

    @ManyToOne
    @JoinColumn(name="Address_Id", insertable = false, updatable = false)
    private Address address;


Something like this at least. The key is that the intermediate entity needs and identifier property which in this case is a composite key.

I haven't tested this, but basically just tried to modify an example out of Java Persistence with Hibernate. If you want to know more I highly recommend getting hold of a copy.

Hope this helps.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 12, 2008 4:01 am 
Beginner
Beginner

Joined: Mon Aug 13, 2007 2:37 am
Posts: 22
Hardy,

I'm not using AddressId and BusinessId as a composite key in the Business_Address table. Business_Address_Id is the primary key in the table.

So, what's the difference between the "Id" that you suggested and "Business_Address_Id"?

Also, in the FullTextSession query:

this returns results:
query = parser.parse("businessName:" + keywords + "~");

however, this DOES NOT return results:
query = parser.parse("businessAddresses.address.cityName:" + criteria_.cityName + "~");

somehow, only data in the main table is being found, not the associated tables.

What's wrong with my configuration??


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 12, 2008 8:29 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

how and where do you use @IndexedEmbedded and @Field in your entities? I assume you have @IndexedEmbedded on businessAddresses in AbstractBusinessCbo and address in AbstractBusinessAddress. Besides, within AbstractAddressCbo you have at least the property cityName annotated with @Field. Right?

I think it is time you had a look at your indexed data. Using Luke will help you understand what's actually happening and what's is getting indexed under which field name. See http://hibernate.org/440.html.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Sun May 18, 2008 3:32 pm 
Beginner
Beginner

Joined: Mon Aug 13, 2007 2:37 am
Posts: 22
My Search is still not working. Can you tell me what I'm doing wrong in my 3 class configuration:

BUSINESS table
Code:

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name = "Busines")
@Indexed(index="indexes/businesses")
public abstract class AbstractBusinessCbo  implements java.io.Serializable {


    // Fields   
   @Id
   @DocumentId
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "BUSINESS_ID", nullable = false)
     private Integer businessId;
     
     @Column(name = "BUSINESS_NAME")
   @Field(index=Index.TOKENIZED)
     private String businessName;
     
     @ContainedIn
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
     @JoinTable(name="BUSINESS_ADDRESS",
              joinColumns={@JoinColumn(name = "BUSINESS_ID")},
              inverseJoinColumns={@JoinColumn(name = "ADDRESS_ID")})
     @IndexedEmbedded
     private Set businessAddresses = new HashSet(0);



ADDRESS table:
Code:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name = "Address")
@Indexed(index="indexes/addresses")
public abstract class AbstractAddressCbo  implements java.io.Serializable {

   @Id
   @DocumentId
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "ADDRESS_ID", nullable = false)
     private Integer addressId;
   
     private Integer countryId;
     private String addressLine1;
     private String addressLine2;
     
   @Column(name = "CITY_NAME")
   @Field(index=Index.TOKENIZED)
     private String cityName;
   
   @Column(name = "STATE")
   @Field(index=Index.TOKENIZED)
     private String state;
     
     @ContainedIn
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
          @JoinTable(name="BUSINESS_ADDRESS",
              joinColumns={@JoinColumn(name = "ADDRESS_ID")},
              inverseJoinColumns={@JoinColumn(name = "BUSINESS_ID")})
     @IndexedEmbedded
     private Set businessAddresses = new HashSet(0);


BUSINESS_ADDRESS table:
Code:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Table(name = "BusinessAddress")
@Indexed(index="indexes/businessAddresses")
public abstract class AbstractBusinessAddress  implements java.io.Serializable {


    // Fields 
   
   @javax.persistence.Id
   @EmbeddedId
   @DocumentId
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "BUSINESS_ADDRESS_ID", nullable = false)
     private Integer businessAddressId;
   
   
    @Embeddable
    public static class Id implements java.io.Serializable {

       @Column(name = "BUSINESS_ID")
       private Integer businessId;

       @Column(name = "ADDRESS_ID")
       private Integer addressId;

      public Id() {}

      public Id( Integer businessId, Integer addressId) {

         this.businessId = businessId;
         this.addressId = addressId;
      }

    }

    @EmbeddedId
    private Id id = new Id();

     
    @ManyToOne
    @JoinColumn(name="ADDRESS_ID", insertable = false, updatable = false)
     private AddressCbo address;
     
    @ManyToOne
    @JoinColumn(name="BUSINESS_ID", insertable = false, updatable = false)
     private BusinessCbo busines;


FULLTEXT QUERY:
Code:

                  FullTextSession fullTextSession = Search.createFullTextSession( session );
                  QueryParser parser = new QueryParser("businessId", new StandardAnalyzer());
                  
                  org.apache.lucene.search.Query query = parser.parse("businessName:" + keywords + "~");
                  query = parser.parse("businessAddresses.address.cityName:" + criteria_.cityName + "~");
                  
                  searchQry = fullTextSession.createFullTextQuery(query, BusinessCbo.class);
               countQry = searchQry;
               result = paginator.getPaginatdResult(session,countQry,searchQry,paginationControl_);



Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 4:40 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I think you might be missing an additional @IndexedEmbedded in AbstractBusinessAddress.

Code:
    @ManyToOne
    @JoinColumn(name="ADDRESS_ID", insertable = false, updatable = false)
     @IndexedEmbedded
     private AddressCbo address;


Other than that I recommend you to add some debug trace to see which objects are getting indexed (what fields are set, how many elements in the set, ...). You can check then the index (using Luke) to see what made it into it and what not. Many times problems are data related.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 21, 2008 3:47 am 
Beginner
Beginner

Joined: Mon Aug 13, 2007 2:37 am
Posts: 22
I took a look at the indexed data using Luke and it looks fine. Considering the fact that I have never used Hibernate Search or the Lucene Luke tool before. So, I could be wrong.

The following fields that are in the 3 index documents:
Code:
businessAddresses index:
<address.addressId>
<address.cityName>
<address.state>
<busines.businessId>
<business.businessName>
<businessAddressId>

addresses index:
<address.addressId>
<address.cityName>
<address.state>


businesses index:
<busines.businessId>
<business.businessName>


For each of the fields, their corresponding values look right. So, I'm wondering if the index fields generated in each of the 3 document is correct. Also, could there be the query I'm using?

I'm really stuck...


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 21, 2008 11:12 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I recommend you read through this part of the online documentation: http://www.hibernate.org/hib_docs/search/reference/en/html_single/#d0e1322. The example Place->Address->Owner is pretty much what you are after. At least I think though.

Also, you don't have to annotate each entity with @Indexed. Given your example query it would be enough to annotate AbstractBusinessCbo. If this is the main entity you want to query (meaning the result of the query is a list of BusinessCbo entities). You only need to annotate the other entities with @Indexed in case you want to query them separately.

This said the businesses index is the one to look at. It should contain the following fields:

Code:
<businessId>
<businessName>
<businessAddresses.address.cityName>
<businessAddresses.address.state>


I've also just seen that you are using @ContainedIn the wrong way. @ContainedIn is intended for the 'other end' of the @IndexedEmbedded annotation (it is required in order to update the index in case the embedded instance changes).

One other thing which comes to my mind is your actual class hierarchy. If I understand correctly all your classes are abstract and you are indexing actual subclasses? It probably works, but I was just wondering how the whole lot looks like.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 03, 2008 5:01 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
The already published chapters of Hibernate Search in Action go into more detailed about all that too.

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.