/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.jdo.ex2;
import java.util.Collection;
import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import org.zoodb.jdo.ZooJdoHelper;
/**
* Slightly advanced example that uses inheritance, indexing and navigation.
* The queries show path queries and the use of Java methods in queries.
* Note that JDOQL / ZooDB support only some methods that are available in
* normal Java classes.
*/
public class Example2Main {
private static final String DB_FILE = "example2.zdb";
private PersistenceManager pm;
public static void main(final String[] args) {
new Example2Main().run();
}
private void run() {
ZooJdoHelper.removeDb(DB_FILE);
System.out.println("> Inserting data ...");
insertData();
System.out.println("> Data insertion complete!");
System.out.println("> Running queries ...");
executeQueries();
System.out.println("> Queries complete!");
}
private void insertData() {
pm = ZooJdoHelper.openOrCreateDB(DB_FILE);
pm.currentTransaction().begin();
School school = new School("Good School");
Teacher t1 = new Teacher("Alan Turing", 1100.00);
Teacher t2 = new Teacher("Albert Einstein", 4056);
Teacher t3 = new Teacher("Adam Ries", 7.36);
Teacher t4 = new Teacher("Archimedes", 34.32);
school.addTeacher(t1);
school.addTeacher(t2);
school.addTeacher(t3);
school.addTeacher(t4);
Student s1 = new Student("Bart", 1);
Student s2 = new Student("Lisa", 2);
school.addStudent(s1);
school.addStudent(s2);
Course cAlg = new Course(t1, "Algebra");
Course cSpo = new Course(t2, "Physics");
Course cEng = new Course(t4, "Engineering");
school.addCourse(cAlg);
school.addCourse(cSpo);
school.addCourse(cEng);
cAlg.addStudents(s2);
cSpo.addStudents(s1, s2);
//We only store the root object, school. Everything else is stored transitively, because
//it is referenced from 'school'.
pm.makePersistent(school);
//define a non-unique index on the name of all Teachers and Students
ZooJdoHelper.createIndex(pm, Person.class, "name", false);
pm.currentTransaction().commit();
pm.close();
pm = null;
}
private void executeQueries() {
pm = ZooJdoHelper.openDB(DB_FILE);
pm.currentTransaction().begin();
// All people (show names).
queryForPeople();
// All courses (titles) with given teacher.
queryForCoursesByTeacher("Albert Einstein");
// The course with the most students.
queryForCoursesWithMaxStudentCount();
// All courses with 2 students.
queryForCoursesWithXStudents(2);
// Find all courses whose teacher have a first name and a last name
queryForCoursesWithTeachersWithFirstAndLastName();
pm.currentTransaction().commit();
pm.close();
pm = null;
}
private void queryForPeople() {
Extent<Person> persons = pm.getExtent(Person.class);
System.out.println(">> Query for People instances returned results:");
for (Person person : persons) {
System.out.println(">> - " + person.getName());
}
}
/**
* Example for a path query on Course.teacher.name == myName.
* @param name
*/
@SuppressWarnings("unchecked")
private void queryForCoursesByTeacher(String name) {
System.out.println(">> Query for courses by teacher " + name + " returned:");
//using reference in query
Query q = pm.newQuery(Course.class, "teacher.name == '" + name + "'");
Collection<Course> courses = (Collection<Course>)q.execute();
for (Course c : courses) {
System.out.println(">> - " + c.getName() + " by " + c.getTeacher().getName());
}
}
/**
* This example demonstrates that using 'navigation'may often be a good alternative
* for queries, especially if the term in question (collection.size()) cannot be indexed yet.
*/
private void queryForCoursesWithMaxStudentCount() {
//TODO `MAX` in queries doesn't work yet, so we use navigation
Extent<Course> courses = pm.getExtent(Course.class);
Course maxCourse = null;
int maxStudents = -1;
for (Course c: courses) {
if (c.getStudents().size() > maxStudents) {
maxStudents = c.getStudents().size();
maxCourse = c;
}
}
if (maxCourse != null) {
System.out.println(">> Query for course with most students returned: " +
maxCourse.getName());
} else {
System.out.println(">> Query for course with most students returned no courses.");
}
}
/**
* This example demonstrates how many Java methods of Java SE classes can
* be used in queries. Not that not all methods can be used.
*/
@SuppressWarnings("unchecked")
private void queryForCoursesWithXStudents(int studentCount) {
System.out.println(">> Query for courses with " + studentCount + " students:");
//using Java method in query
Query q = pm.newQuery(Course.class, "students.size() == " + studentCount + "");
Collection<Course> courses = (Collection<Course>)q.execute();
for (Course c : courses) {
System.out.println(">> - " + c.getName() + " has size: " + c.getStudents().size());
}
}
/**
* This example combines a path query with a Java method call on the String class.
*/
@SuppressWarnings("unchecked")
private void queryForCoursesWithTeachersWithFirstAndLastName() {
System.out.println(">> Query for courses whose teacher have a frist and last name:");
//using Java method in query
Query q = pm.newQuery(Course.class, "teacher.name.indexOf(' ') >= 1");
Collection<Course> courses = (Collection<Course>)q.execute();
for (Course c : courses) {
System.out.println(">> - " + c.getName() +
" has teacher: " + c.getTeacher().getName());
}
}
}