The following examples show how to pass parameters to the Native Query predicate. Store Pilots function is used to fill in the database.
Using predicate constructor to specify the querying parameter.
01private static void getTestPilots() { 02
ObjectContainer container = database(); 03
if (container != null) { 04
try { 05
List<Pilot> result = container.query(new PilotNamePredicate( 06
"Test")); 07
listResult(result); 08
} catch (Exception ex) { 09
System.out.println("System Exception: " + ex.getMessage()); 10
} finally { 11
closeDatabase(); 12
} 13
} 14
}
01private static class PilotNamePredicate extends Predicate<Pilot> { 02
private String startsWith; 03
04
public PilotNamePredicate(String startsWith) { 05
this.startsWith = startsWith; 06
} 07
08
public boolean match(Pilot pilot) { 09
return pilot.getName().startsWith(startsWith); 10
} 11
}
Using a function to process the NQ.
01private static void getProfessionalPilots() { 02
ObjectContainer container = database(); 03
if (container != null) { 04
try { 05
List<Pilot> result = byNameBeginning("Professional"); 06
listResult(result); 07
} catch (Exception ex) { 08
System.out.println("System Exception: " + ex.getMessage()); 09
} finally { 10
closeDatabase(); 11
} 12
} 13
}
1private static List<Pilot> byNameBeginning(final String startsWith) { 2
return database().query(new Predicate<Pilot>() { 3
public boolean match(Pilot pilot) { 4
return pilot.getName().startsWith(startsWith); 5
} 6
}); 7
}
The following example shows how to correctly implement parameterized NQ predicate for querying derived classes.
Let's use the class hierarchy as defined in Persistent Classes.
PersonNamePredicate will be used for querying classes derived from Person:
01private static class PersonNamePredicate<T extends Person> extends 02
Predicate<T> { 03
private String startsWith; 04
05
public PersonNamePredicate(String startsWith) { 06
this.startsWith = startsWith; 07
} 08
09
public PersonNamePredicate(Class<T> clazz, String startsWith) { 10
super(clazz); 11
this.startsWith = startsWith; 12
} 13
14
public boolean match(T candidate) { 15
return candidate.getName().startsWith(startsWith); 16
} 17
}
Let's save some Pilot and Trainee objects:
01private static void storePersons() { 02
new File(DB4O_FILE_NAME).delete(); 03
ObjectContainer container = database(); 04
if (container != null) { 05
try { 06
Trainee trainee; 07
// store OBJECT_COUNT pilots and trainees 08
for (int i = 0; i < OBJECT_COUNT; i++) { 09
trainee = new Trainee("Trainee #" + i, new Pilot( 10
"Professional Pilot #" + i, i)); 11
container.set(trainee); 12
} 13
// store a new trainee with a "Training" pilot 14
trainee = new Trainee("Trainee #1", new Pilot( 15
"Training Pilot #1", 20)); 16
container.set(trainee); 17
container.commit(); 18
} catch (Db4oException ex) { 19
System.out.println("Db4o Exception: " + ex.getMessage()); 20
} catch (Exception ex) { 21
System.out.println("System Exception: " + ex.getMessage()); 22
} finally { 23
closeDatabase(); 24
} 25
} 26
}
Now we have both Pilot and Trainee objects starting from "Train". What should we do to retrieve only Trainee objects?
01private static void getTrainees() { 02
ObjectContainer container = database(); 03
if (container != null) { 04
try { 05
// query for Trainee objects starting with "Train". 06
// Wrongly created predicate mixes Trainee and Pilot 07
// objects and creates a resultset based on only "Tr" 08
// criteria (class of an object is not considered) 09
10
testQuery(container, createPredicateWrong(Trainee.class, 11
"Train")); 12
// Correctly created result set returns only objects 13
// of the requested class 14
testQuery(container, createPredicateCorrect(Trainee.class, 15
"Train")); 16
} catch (Exception ex) { 17
System.out.println("System Exception: " + ex.getMessage()); 18
} finally { 19
closeDatabase(); 20
} 21
} 22
}
01private static void testQuery(ObjectContainer container, 02
Predicate<Trainee> predicate) { 03
List<Trainee> result = container.query(predicate); 04
System.out.println(result.size()); 05
try { 06
for (Trainee trainee : result) { 07
System.out.println(trainee); 08
} 09
} catch (Exception ex) { 10
System.out.println(ex.toString()); 11
} 12
}
1private static <T extends Person> Predicate<T> createPredicateWrong( 2
Class<T> clazz, String startsWith) { 3
return new PersonNamePredicate<T>(startsWith); 4
}
1private static <T extends Person> Predicate<T> createPredicateCorrect( 2
Class<T> clazz, String startsWith) { 3
return new PersonNamePredicate<T>(clazz, startsWith); 4
}
You can see that in order to get the correct results we need to supply our preicate class with the queried class, otherwise both Pilot and Trainee objects will be included in the result set.