Hello everyone,
I've been researching Hibernate search and have run into a issue that I would like help with. I've read and search the docs and looked in the test code that came with the distro, but I have not found a solution
I am using hibernate version 3.2.2ga and search version 3.0.0ga, JDK version 1.5.0_10
I have the following entities and EJB defined as below:
Code:
UserImpl.java:
@Entity
@Table(name = "TEST_USER")
@Indexed
public class UserImpl implements User
{
private static final long serialVersionUID = -5664137986778262321L;
private long userId;
private String name = null;
public UserImpl()
{
super();
}
@Id
@GeneratedValue
@Column(name = "USER_ID")
@DocumentId
public long getUserId()
{
return userId;
}
@SuppressWarnings("unused")
private void setUserId(long userId)
{
this.userId = userId;
}
@Column(name = "NAME", length = 255, nullable = false)
@Field(index=Index.TOKENIZED)
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
TestObjectImpl.java:
@Entity
@Table(name = "TEST_OBJECT")
@Indexed
public class TestObjectImpl implements TestObject
{
private static final long serialVersionUID = -6413459610770508768L;
private long testObjectId;
private User createdByUser = null;
public TestObjectImpl()
{
super();
}
@Id
@GeneratedValue
@Column(name = "TEST_OBJECT_ID")
@DocumentId
public long getTestObjectId()
{
return testObjectId;
}
@SuppressWarnings("unused")
private void setTestObjectId(long testObjectId)
{
this.testObjectId = testObjectId;
}
@ManyToOne(targetEntity = UserImpl.class, fetch=FetchType.EAGER, cascade = CascadeType.MERGE)
@JoinColumn(name = "CREATED_BY_USER_ID", referencedColumnName = "USER_ID")
@IndexedEmbedded()
public User getCreatedByUser()
{
return createdByUser;
}
public void setCreatedByUser(User createdByUser)
{
this.createdByUser = createdByUser;
}
}
EJB Impl:
@Stateless
public class TestEJBImpl implements TestEJB
{
@PersistenceContext(unitName = "foo")
protected EntityManager entityManager;
public TestObject createATestObject()
{
User user = new UserImpl();
user.setName("BillyBob");
entityManager.persist(user);
TestObject test = new TestObjectImpl();
test.setCreatedByUser(user);
entityManager.persist(test);
return test;
}
public List<TestObject> searchForTestObject(String userNameToken)
{
FullTextEntityManager fullTextEntityManager = Search.createFullTextEntityManager(entityManager);
MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[] {"createdByUser.name"},
new StandardAnalyzer());
org.apache.lucene.search.Query query;
try
{
query = parser.parse("createdByUser.name:" + userNameToken);
}
catch (ParseException e)
{
e.printStackTrace();
return null;
}
FullTextQuery hibQuery = fullTextEntityManager.createFullTextQuery(query, TestObjectImpl.class);
return hibQuery.getResultList();
}
}
TestClient code snippet:
TestObject testObj = testEjb.createATestObject();
System.out.println(testObj.getTestObjectId() + ":" + testObj.getCreatedByUser().getName());
List<TestObject> searchResults = testEjb.searchForTestObject(testObj.getCreatedByUser().getName());
if(searchResults == null || searchResults.isEmpty())
{
System.out.println("did not find any");
System.exit(0);
}
else
{
for(TestObject foundObj : searchResults)
{
System.out.println("found " + foundObj.getTestObjectId() + ":" + foundObj.getCreatedByUser().getName());
}
System.exit(0);
}
test client output:
2000022:BillyBob
did not find any
When the relationship to UserImpl is declared using the interface as the type of the field in TestObjectImpl as above, I see the the createdByUser is not indexed. When I change the member variable (and associated getters/setters to UserImpl instead of User) I do see that the field is indexed properly. I have confirmed this by changing the TestObjectImpl as follows:
Code:
TestObjectImpl.java:
@Entity
@Table(name = "TEST_OBJECT")
@Indexed
public class TestObjectImpl implements TestObject
{
private static final long serialVersionUID = -6413459610770508768L;
private long testObjectId;
private UserImpl createdByUser = null;
public TestObjectImpl()
{
super();
}
@Id
@GeneratedValue
@Column(name = "TEST_OBJECT_ID")
@DocumentId
public long getTestObjectId()
{
return testObjectId;
}
@SuppressWarnings("unused")
private void setTestObjectId(long testObjectId)
{
this.testObjectId = testObjectId;
}
@ManyToOne(targetEntity = UserImpl.class, fetch=FetchType.EAGER, cascade = CascadeType.MERGE)
@JoinColumn(name = "CREATED_BY_USER_ID", referencedColumnName = "USER_ID")
@IndexedEmbedded()
public UserImpl getCreatedByUser()
{
return createdByUser;
}
public void setCreatedByUser(User createdByUser)
{
this.createdByUser = (UserImpl)createdByUser;
}
}
test client output:
2000024:BillyBob
found 2000024:BillyBob
So, the question is this: How can I go about making this work while using the targetEntity to point to the implementing class but having the field and methods using the interface? I need to do this for reasons outside of the scope of this post.
I've done some searching, and I have not been able to find anything of help to me.
Thanks for any help
-Sharath