Hi Hardy,
thanks for the quick reply.
hardy.ferentschik wrote:
That said, the stacktrace does not seem to come out of the Search code directly, but rather out of a criteria query. Maybe it would help to see some code.
That's right. The exception does occur, when i call 'list()' on the FullTextQuery object, which is returned by HibernateSearch. Creating the Query object (i.e. calling 'createFullTextQuery()' on the Session) does not raise an exception. But doesn't this mean, that the FullTextQuery returned by HibernateSearch is not correct? It contains '_id' where it should contain 'id'.
The code of the remaining files (Main.java, EventPropertyAccessor.java) is below.
Regards, Ralf!
Code:
package test;
import java.util.Date;
import java.util.List;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
public class Main {
private static SessionFactory factory;
static {
factory = new Configuration().configure().buildSessionFactory();
}
public static void main(String[] args) throws Exception {
createEvents();
indexEvents();
List<Event> result1 = searchEvents("Event");
for (Event event : result1) {
System.out.println(event.getTitle());
}
factory.close();
}
private static void createEvents() {
Session session = factory.getCurrentSession();
Transaction tx = session.beginTransaction();
Event e1 = new Event();
e1.setDate(new Date());
e1.setTitle("Event One");
session.save(e1);
Event e2 = new Event();
e2.setDate( new Date());
e2.setTitle("Event two");
session.save(e2);
tx.commit();
}
private static List<Event> searchEvents(String queryString) throws ParseException {
String[] fields = new String[] {"title"};
return search(queryString, fields, Event.class);
}
private static <T> List<T> search(String queryString, String[] fields, Class<T> theClass) throws ParseException {
Session session = factory.getCurrentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
Query query = parser.parse( queryString);
org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(query, theClass);
@SuppressWarnings("unchecked")
List<T> result = hibQuery.list();
tx.commit();
return result;
}
private static void indexEvents() {
Session session = factory.getCurrentSession();
FullTextSession fullTextSession = Search.getFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
@SuppressWarnings("unchecked")
List<Event> events = session.createQuery("from Event as event").list();
for (Event event : events) {
fullTextSession.index(event);
}
tx.commit();
}
}
Code:
package test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.PropertyAccessException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.Setter;
public class EventPropertyAccessor implements PropertyAccessor {
@SuppressWarnings("unchecked")
public Getter getGetter(Class clazz, String propertyName) throws PropertyNotFoundException {
return createGetter(clazz, propertyName);
}
@SuppressWarnings("unchecked")
public Setter getSetter(Class clazz, String propertyName) throws PropertyNotFoundException {
return createSetter(clazz, propertyName);
}
private static Getter createGetter(Class<?> clazz, String propertyName) {
Method getterMethod = findGetterMethod(clazz, propertyName);
return new BasicGetter(clazz, getterMethod, propertyName);
}
private static Setter createSetter(Class<?> theClass, String propertyName) {
Method getter = findGetterMethod(theClass, propertyName);
try {
Method m = theClass.getDeclaredMethod(getter.getName(), getter.getReturnType());
m.setAccessible(true);
return new BasicSetter(theClass, m, propertyName);
} catch (NoSuchMethodException e) {
throw new PropertyNotFoundException("Could not find a setter for property " + propertyName + " in class " +
theClass.getName());
}
}
private static final Method findGetterMethod(Class<?> theClass, String propertyName)
throws PropertyNotFoundException {
try {
Method m = theClass.getDeclaredMethod("_" + propertyName, new Class<?>[0]);
m.setAccessible(true);
return m;
} catch (NoSuchMethodException e) {
throw new PropertyNotFoundException("Could not find a getter for " + propertyName + " in class " +
theClass.getName());
}
}
private static final class BasicGetter implements Getter {
private static final long serialVersionUID = 796233579190385370L;
private Class<?> clazz;
private final transient Method method;
private final String propertyName;
BasicGetter(Class<?> clazz, Method method, String propertyName) {
this.clazz = clazz;
this.method = method;
this.propertyName = propertyName;
}
public Object get(Object target) throws HibernateException {
try {
return method.invoke(target, (Object[]) null);
} catch (InvocationTargetException ite) {
throw new PropertyAccessException(ite, "Exception occurred inside", false, clazz, propertyName);
} catch (IllegalAccessException iae) {
throw new PropertyAccessException(iae, "IllegalAccessException occurred while calling", false, clazz,
propertyName);
// cannot occur
} catch (IllegalArgumentException iae) {
throw new PropertyAccessException(iae, "IllegalArgumentException occurred calling", false, clazz,
propertyName);
}
}
@SuppressWarnings("unchecked")
public Object getForInsert(Object target, Map mergeMap, SessionImplementor session) {
return get(target);
}
public Class<?> getReturnType() {
return method.getReturnType();
}
public Method getMethod() {
return method;
}
public String getMethodName() {
return method.getName();
}
@Override
public String toString() {
return "BasicGetter(" + clazz.getName() + '.' + propertyName + ')';
}
Object readResolve() {
return EventPropertyAccessor.createGetter(clazz, propertyName);
}
}
private static final class BasicSetter implements Setter {
private static final long serialVersionUID = -8350321782961402054L;
private Class<?> clazz;
private final transient Method method;
private final String propertyName;
BasicSetter(Class<?> clazz, Method method, String propertyName) {
this.clazz = clazz;
this.method = method;
this.propertyName = propertyName;
}
public void set(Object target, Object value, SessionFactoryImplementor factory) throws HibernateException {
try {
method.invoke(target, new Object[] { value });
} catch (NullPointerException npe) {
if (value == null && method.getParameterTypes()[0].isPrimitive()) {
throw new PropertyAccessException(npe, "Null value was assigned to a property of primitive type", true,
clazz, propertyName);
}
throw new PropertyAccessException(npe, "NullPointerException occurred while calling", true, clazz,
propertyName);
} catch (InvocationTargetException ite) {
throw new PropertyAccessException(ite, "Exception occurred inside", true, clazz, propertyName);
} catch (IllegalAccessException iae) {
throw new PropertyAccessException(iae, "IllegalAccessException occurred while calling", true, clazz,
propertyName);
// cannot occur
} catch (IllegalArgumentException iae) {
if (value == null && method.getParameterTypes()[0].isPrimitive()) {
throw new PropertyAccessException(iae, "Null value was assigned to a property of primitive type", true,
clazz, propertyName);
}
throw new PropertyAccessException(iae, "IllegalArgumentException occurred while calling", true, clazz,
propertyName);
}
}
public Method getMethod() {
return method;
}
public String getMethodName() {
return method.getName();
}
Object readResolve() {
return EventPropertyAccessor.createSetter(clazz, propertyName);
}
@Override
public String toString() {
return "BasicSetter(" + clazz.getName() + '.' + propertyName + ')';
}
}
}
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<property name="connection.url">jdbc:derby://localhost:1527/HibernateTest</property>
<property name="connection.username">test</property>
<property name="connection.password">test</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.DerbyDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<!-- Hibernate search properties -->
<property name="hibernate.search.default.directory_provider">org.hibernate.search.store.RAMDirectoryProvider</property>
<mapping resource="Event.hbm.xml"/>
<!-- Register event listeners -->
<event type="post-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
<event type="post-insert">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
<event type="post-delete">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
</session-factory>
</hibernate-configuration>