Relations on one entity : Self Join « JPA « Java






Relations on one entity


/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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());
        }
    }
}
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 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  childName  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;
    }

}





           
       








JPA-relations.zip( 8 k)

Related examples in the same category

1.Join Member Entities