mirror of https://github.com/apache/openjpa.git
Added 'relations' example to demonstrate defining and querying relations in JPA; also upgraded the version of Derby included in the release for example usage to be 10.2.1.6 in order to keep up
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@475498 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
728413153f
commit
08a615efad
|
@ -39,7 +39,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
<version>10.1.3.1</version>
|
<version>10.2.1.6</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -17,6 +17,16 @@
|
||||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
We need to enumerate each persistent class first in the persistence.xml
|
||||||
|
See: http://issues.apache.org/jira/browse/OPENJPA-78
|
||||||
|
-->
|
||||||
|
<persistence-unit name="none" transaction-type="RESOURCE_LOCAL">
|
||||||
|
<class>hellojpa.Message</class>
|
||||||
|
<class>relations.Deity</class>
|
||||||
|
</persistence-unit>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
A persistence unit is a set of listed persistent entities as well
|
A persistence unit is a set of listed persistent entities as well
|
||||||
the configuration of an EntityManagerFactory. We configure each
|
the configuration of an EntityManagerFactory. We configure each
|
||||||
|
@ -26,11 +36,14 @@
|
||||||
<!--
|
<!--
|
||||||
The default provider can be OpenJPA, or some other product.
|
The default provider can be OpenJPA, or some other product.
|
||||||
This element is optional if OpenJPA is the only JPA provider
|
This element is optional if OpenJPA is the only JPA provider
|
||||||
in the current classloading environment.
|
in the current classloading environment, but can be specified
|
||||||
|
in cases where there are multiple JPA implementations available.
|
||||||
-->
|
-->
|
||||||
|
<!--
|
||||||
<provider>
|
<provider>
|
||||||
org.apache.openjpa.persistence.PersistenceProviderImpl
|
org.apache.openjpa.persistence.PersistenceProviderImpl
|
||||||
</provider>
|
</provider>
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- We must enumerate each entity in the persistence unit -->
|
<!-- We must enumerate each entity in the persistence unit -->
|
||||||
<class>hellojpa.Message</class>
|
<class>hellojpa.Message</class>
|
||||||
|
@ -54,4 +67,9 @@
|
||||||
-->
|
-->
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
|
<!-- persistence unit for the "relations" example -->
|
||||||
|
<persistence-unit name="relations" transaction-type="RESOURCE_LOCAL">
|
||||||
|
<class>relations.Deity</class>
|
||||||
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package relations;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entity that contains relations corresponding to family tree relations.
|
||||||
|
* This entity demonstrates the following JPA features:
|
||||||
|
*
|
||||||
|
* 1. Enum fields (gender)
|
||||||
|
* 2. @OneToOne relations
|
||||||
|
* 3. @OneToMany relations
|
||||||
|
* 4. Named queries
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@NamedQueries({
|
||||||
|
|
||||||
|
// a sibling shares a mother and a father
|
||||||
|
@NamedQuery(name="siblings", query="select distinct sibling1 "
|
||||||
|
+ "from Deity sibling1, Deity sibling2 where "
|
||||||
|
+ "sibling1.father = sibling2.father "
|
||||||
|
+ "and sibling1.mother = sibling2.mother "
|
||||||
|
+ "and sibling2 = ?1 and sibling1 <> ?1"),
|
||||||
|
|
||||||
|
// a half-siling shares a mother or a father, but not both
|
||||||
|
@NamedQuery(name="half-siblings", query="select distinct sibling1 "
|
||||||
|
+ "from Deity sibling1, Deity sibling2 where "
|
||||||
|
+ "((sibling1.father = sibling2.father "
|
||||||
|
+ "and sibling1.mother <> sibling2.mother) "
|
||||||
|
+ "or (sibling1.father <> sibling2.father "
|
||||||
|
+ "and sibling1.mother = sibling2.mother)) "
|
||||||
|
+ "and sibling2 = ?1 and sibling1 <> ?1"),
|
||||||
|
|
||||||
|
// a half-siling shares a mother or a father, but not both
|
||||||
|
@NamedQuery(name="half-siblings", query="select distinct sibling1 "
|
||||||
|
+ "from Deity sibling1, Deity sibling2 where "
|
||||||
|
+ "((sibling1.father = sibling2.father "
|
||||||
|
+ "and sibling1.mother <> sibling2.mother) "
|
||||||
|
+ "or (sibling1.father <> sibling2.father "
|
||||||
|
+ "and sibling1.mother = sibling2.mother)) "
|
||||||
|
+ "and sibling2 = ?1 and sibling1 <> ?1"),
|
||||||
|
|
||||||
|
// a cousin shares a grandparent, but is not a sibling
|
||||||
|
@NamedQuery(name="cousins", query="select distinct cousin1 "
|
||||||
|
+ "from Deity cousin1, Deity cousin2 where "
|
||||||
|
+ "("
|
||||||
|
+ "cousin1.father.father = cousin2.father.father "
|
||||||
|
+ "or cousin1.father.mother = cousin2.father.mother "
|
||||||
|
+ "or cousin1.mother.father = cousin2.mother.father "
|
||||||
|
+ "or cousin1.mother.mother = cousin2.mother.mother) "
|
||||||
|
+ "and (cousin1.father <> cousin2.father) "
|
||||||
|
+ "and (cousin1.mother <> cousin2.mother) "
|
||||||
|
+ "and cousin2 = ?1 and cousin1 <> ?1")
|
||||||
|
})
|
||||||
|
public class Deity implements Serializable {
|
||||||
|
// the Id is the name, which is generally a bad idea, but we are
|
||||||
|
// confident that diety names will be unique
|
||||||
|
@Id
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Basic @Enumerated(EnumType.STRING)
|
||||||
|
private Gender gender;
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.ALL)
|
||||||
|
private Deity mother;
|
||||||
|
|
||||||
|
@OneToOne(cascade=CascadeType.ALL)
|
||||||
|
private Deity father;
|
||||||
|
|
||||||
|
@OneToMany(cascade=CascadeType.ALL)
|
||||||
|
private Set<Deity> children;
|
||||||
|
|
||||||
|
public static enum Gender { MALE, FEMALE }
|
||||||
|
|
||||||
|
|
||||||
|
public Deity(String name, Gender gender) {
|
||||||
|
this.name = name;
|
||||||
|
this.gender = gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Business methods follow
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* She's having a baby...
|
||||||
|
*
|
||||||
|
* @param firstName the baby name
|
||||||
|
* @return the new child
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the person is not a woman, or
|
||||||
|
* if the person is unmarried (illegitimate
|
||||||
|
* children are not yet supported)
|
||||||
|
*/
|
||||||
|
public Deity giveBirth(String childName, Deity childFather, Gender gender) {
|
||||||
|
if (this.gender != Gender.FEMALE)
|
||||||
|
throw new IllegalArgumentException("Only women can have children!");
|
||||||
|
|
||||||
|
if (childName == null)
|
||||||
|
throw new IllegalArgumentException("No child name!");
|
||||||
|
|
||||||
|
// create the child
|
||||||
|
Deity child = new Deity(childName, gender);
|
||||||
|
|
||||||
|
// set the parents in the children...
|
||||||
|
child.mother = this;
|
||||||
|
|
||||||
|
// add the child to this member's children
|
||||||
|
if (children == null)
|
||||||
|
children = new HashSet<Deity>();
|
||||||
|
children.add(child);
|
||||||
|
|
||||||
|
if (childFather != null) {
|
||||||
|
child.father = childFather;
|
||||||
|
if (childFather.children == null)
|
||||||
|
childFather.children = new HashSet<Deity>();
|
||||||
|
childFather.children.add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// Property accessor methods follow
|
||||||
|
////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setGender(Gender gender) {
|
||||||
|
this.gender = gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gender getGender() {
|
||||||
|
return this.gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setMother(Deity mother) {
|
||||||
|
this.mother = mother;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deity getMother() {
|
||||||
|
return this.mother;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setFather(Deity father) {
|
||||||
|
this.father = father;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deity getFather() {
|
||||||
|
return this.father;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setChildren(Set<Deity> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Deity> getChildren() {
|
||||||
|
return this.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package relations;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
// import the enums for MALE and FEMALE
|
||||||
|
import static relations.Deity.Gender.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A very simple, stand-alone program that stores a new entity in the
|
||||||
|
* database and then performs a query to retrieve it.
|
||||||
|
*/
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Create a new EntityManagerFactory using the System properties.
|
||||||
|
// The "relations" name will be used to configure based on the
|
||||||
|
// corresponding name in the META-INF/persistence.xml file
|
||||||
|
EntityManagerFactory factory = Persistence.
|
||||||
|
createEntityManagerFactory("relations", System.getProperties());
|
||||||
|
|
||||||
|
// Create a new EntityManager from the EntityManagerFactory. The
|
||||||
|
// EntityManager is the main object in the persistence API, and is
|
||||||
|
// used to create, delete, and query objects, as well as access
|
||||||
|
// the current transaction
|
||||||
|
EntityManager em = factory.createEntityManager();
|
||||||
|
|
||||||
|
initFamilyTree(em);
|
||||||
|
|
||||||
|
runQueries(em);
|
||||||
|
|
||||||
|
// It is always good to clean up after ourselves
|
||||||
|
em.close();
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a partial family tree of the Greek dieties.
|
||||||
|
*
|
||||||
|
* @param em the EntityManager to use in the persistence process
|
||||||
|
*/
|
||||||
|
public static void initFamilyTree(EntityManager em) {
|
||||||
|
|
||||||
|
// First delete all the members from the database the clean up
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.createQuery("delete from Deity").executeUpdate();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Generation 1
|
||||||
|
Deity uranus = new Deity("Uranus", MALE);
|
||||||
|
Deity gaea = new Deity("Gaea", FEMALE);
|
||||||
|
|
||||||
|
// Generation 2
|
||||||
|
Deity cronus = gaea.giveBirth("Cronus", uranus, MALE);
|
||||||
|
Deity rhea = gaea.giveBirth("Rhea", uranus, FEMALE);
|
||||||
|
Deity coeus = gaea.giveBirth("Coeus", uranus, MALE);
|
||||||
|
Deity phoebe = gaea.giveBirth("Phoebe", uranus, FEMALE);
|
||||||
|
Deity oceanus = gaea.giveBirth("Oceanus", uranus, MALE);
|
||||||
|
Deity tethys = gaea.giveBirth("Tethys", uranus, FEMALE);
|
||||||
|
|
||||||
|
// Generation 3
|
||||||
|
Deity leto = phoebe.giveBirth("Leto", coeus, FEMALE);
|
||||||
|
|
||||||
|
Deity hestia = rhea.giveBirth("Hestia", cronus, FEMALE);
|
||||||
|
Deity pluto = rhea.giveBirth("Pluto", cronus, MALE);
|
||||||
|
Deity poseidon = rhea.giveBirth("Poseidon", cronus, MALE);
|
||||||
|
Deity zeus = rhea.giveBirth("Zeus", cronus, MALE);
|
||||||
|
Deity hera = rhea.giveBirth("Hera", cronus, FEMALE);
|
||||||
|
Deity demeter = rhea.giveBirth("Demeter", cronus, FEMALE);
|
||||||
|
|
||||||
|
// Generation 4
|
||||||
|
Deity iapetus = tethys.giveBirth("Iapetus", coeus, MALE);
|
||||||
|
Deity clymene = new Deity("Clymene", FEMALE);
|
||||||
|
|
||||||
|
Deity apollo = leto.giveBirth("Apollo", zeus, MALE);
|
||||||
|
Deity artemis = leto.giveBirth("Artemis", zeus, MALE);
|
||||||
|
|
||||||
|
Deity persephone = demeter.giveBirth("Persephone", zeus, MALE);
|
||||||
|
|
||||||
|
Deity ares = hera.giveBirth("Ares", zeus, MALE);
|
||||||
|
Deity hebe = hera.giveBirth("Hebe", zeus, FEMALE);
|
||||||
|
Deity hephaestus = hera.giveBirth("Hephaestus", zeus, MALE);
|
||||||
|
|
||||||
|
Deity prometheus = clymene.giveBirth("Prometheus", iapetus, MALE);
|
||||||
|
Deity atlas = clymene.giveBirth("Atlas", iapetus, MALE);
|
||||||
|
Deity epimetheus = clymene.giveBirth("Epimetheus", iapetus, FEMALE);
|
||||||
|
|
||||||
|
Deity dione = new Deity("Dione", FEMALE);
|
||||||
|
dione.giveBirth("Aphrodite", zeus, FEMALE);
|
||||||
|
|
||||||
|
// Begin a new local transaction so that we can persist a new entity
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
// note that we only need to explicitly persist a single root of the
|
||||||
|
// object graph (the family tree, in this case), since we have the
|
||||||
|
// "cascade" annotation on all the relations
|
||||||
|
em.persist(zeus);
|
||||||
|
|
||||||
|
// Commit the transaction, which will cause the entity to
|
||||||
|
// be stored in the database
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run some sample queries against the family tree model.
|
||||||
|
*
|
||||||
|
* @param em the EntityManager to use
|
||||||
|
*/
|
||||||
|
public static void runQueries(EntityManager em) {
|
||||||
|
|
||||||
|
System.out.println("Running query to find all instances..");
|
||||||
|
|
||||||
|
// Perform a simple query for all the Deity entities
|
||||||
|
Query q = em.createQuery("select x from Deity x");
|
||||||
|
|
||||||
|
// Go through each of the entities and print out each of their
|
||||||
|
// messages, as well as the date on which it was created
|
||||||
|
for (Deity m : (List<Deity>)q.getResultList()) {
|
||||||
|
System.out.println(m.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
q = em.createQuery("select x from Deity x "
|
||||||
|
+ "where x.father.name = 'Zeus'");
|
||||||
|
|
||||||
|
for (Deity m : (List<Deity>)q.getResultList()) {
|
||||||
|
System.out.println("Child of Zeus: " + m.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
q = em.createNamedQuery("siblings").
|
||||||
|
setParameter(1, em.getReference(Deity.class, "Rhea"));
|
||||||
|
|
||||||
|
for (Deity m : (List<Deity>)em.createNamedQuery("siblings").
|
||||||
|
setParameter(1, em.getReference(Deity.class, "Rhea")).
|
||||||
|
getResultList()) {
|
||||||
|
System.out.println("Siblings of Rhea: " + m.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Deity m : (List<Deity>)em.createNamedQuery("half-siblings").
|
||||||
|
setParameter(1, em.getReference(Deity.class, "Apollo")).
|
||||||
|
getResultList()) {
|
||||||
|
System.out.println("Half-siblings of Apollo: " + m.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Deity m : (List<Deity>)em.createNamedQuery("cousins").
|
||||||
|
setParameter(1, em.getReference(Deity.class, "Leto")).
|
||||||
|
getResultList()) {
|
||||||
|
System.out.println("Cousins of Leto: " + m.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2006 The Apache Software Foundation.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<project name="relations" default="run">
|
||||||
|
<property name="example" value="relations"/>
|
||||||
|
<import file="../build.xml"/>
|
||||||
|
</project>
|
|
@ -45,7 +45,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
<version>10.1.3.1</version>
|
<version>10.2.1.6</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -343,7 +343,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
<version>10.1.3.1</version>
|
<version>10.2.1.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- jars needed for for docbook -->
|
<!-- jars needed for for docbook -->
|
||||||
|
|
Loading…
Reference in New Issue