More Books
Hibernate: A J2EE Developer's Guide
Hibernate: A J2EE™ Developer's Guide
Table of Contents
Copyright
Acknowledgments
About the Author
Preface
Required Skills
Roadmap
Chapter 1. Overview
Why Object/Relational Mapping?
What Is Hibernate?
Comparing JDBC to Hibernate
Hibernate's Mapping System
Other Java/Database Integration Solutions
How to Obtain and Install
Supported Databases
Chapter 2. Getting Oriented
Application Architecture
Mapping Files
Generating Java Source
Application Configuration
Web Application
JSP Interface
Chapter 3. Starting from Java
Java Object Model
Generated Mapping Files
Generated Schema
Working with Artifacts and Owners
Chapter 4. Starting from an Existing Schema
Initial Schema
Using Middlegen
Generated Mapping Files
Generated Java
Working with the Database
Chapter 5. Mapping Files
Basic Structure
Mapping File Reference
Chapter 6. Persistent Objects
Sessions
Objects and Identity
Life-Cycle Methods
Chapter 7. Relationships
Database Relationships
Java Collection Relationships
Java Class Relationships
Any-Based Relationships
Bi-directional Relationships
Chapter 8. Queries
HQL
HQL Reference
Select
From
Where
Group By
Having
Order By
Criteria Queries
Native SQL Queries
Chapter 9. Transactions
Introduction to Transactions
Optimistic and Pessimistic Locking
Chapter 10. Performance
Finding and Solving Problems
Queries
Inserts
Connection Pooling
Caching
Chapter 11. Schema Management
Updating an Existing Schema
Generating Update and Drop Scripts
Chapter 12. Best Practices, Style Guide, Tips and Tricks
Reducing Code with Inversion of Control
Reducing Session Creation Impact with ThreadLocal
Using Hibernate as an EJB BMP Solution
Integrating with Other Technologies
Applications That Use Hibernate
Strategies for Getting Started
Chapter 13. Future Directions
Hibernate 3.0
EJB 3.0
Here and Now
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X

Working with Artifacts and Owners

This final section of the chapter provides a sample set of operations. The entire class is shown in Listing 3.13, broken up to allow for commentary.

The code shown in Listing 3.13 shows the primary flow for the test application. A SessionFactory is shared throughout the execution of the application. An array of strings is used to describe a set of basic objects. The main() method tests the creation, update, and deletion of a set of objects.

Listing 3.13. Setting Up the Code
package com.cascadetg.ch03;

/** Note that we leverage a JDBC connection for
 * our mass delete code.
 */
import java.sql.Connection;
import java.sql.Statement;

/** Various Hibernate-related imports */
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.tool.hbm2ddl.SchemaUpdate;
import net.sf.hibernate.expression.Order;

public class TestSuite
{
    /** We use this session factory to create our sessions */
    public static SessionFactory sessionFactory;

    /** Our artifact data */
    public static String[] artifactNames =
        {
            "Bast Figurine, Faience",
            "Obsidian Spearpoint, Maglenian Period",
            "Lion Bowl, Unidentified",
            "Golden Torq, Six Inch Diameter",
            "Silver Ring, Roman" };

    static long update_id;

    public static void main(String[] args)
    {
        initialization();
        if (currentCount() == 0)
            System.out.println("initialization OK");

        createObjects();
        if (currentCount() == 5)
            System.out.println("createObjects OK");

        loadAllArtifacts();
        if (currentCount() == 5)
            System.out.println("loadAllArtifacts OK");

        updateOneObject();
        if (currentCount() == 5)
            System.out.println("updateOneObject OK");

        deleteObjects();
        if (currentCount() == 4)
            System.out.println("deleteObjects OK");

        massDelete();
        if (currentCount() == 0)
            System.out.println("massDelete OK");
    }

Listing 3.14 shows the use of HQL to determine the number of artifacts currently in the system. For more information on HQL, see Chapter 8.

Listing 3.14. Obtaining the Current Count
    public static int currentCount()
    {
        System.out.println();
        Session hibernateSession = null;
        Transaction myTransaction = null;
        Integer result = null;
        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction =
                 hibernateSession.beginTransaction();

            String hql =
            "select count(artifact) from Artifact as artifact";

            Query myQuery = hibernateSession.createQuery(hql);

            result = (Integer)myQuery.uniqueResult();
            System.out.println(
                "Current count: " + result.toString());

            myTransaction.commit();

        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                if (hibernateSession != null)
                    hibernateSession.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }
        return result.intValue();
    }

Listing 3.15 shows the standard initialization of a Hibernate application. Note the use of the SchemaUpdate class to ensure that the database schema is brought in line with the current mapping files (see Chapter 11 for more information on schema management).

Listing 3.15. Setting Up the Code
    /** Loads the Hibernate configuration information,
     * sets up the database and the Hibernate session factory.
     */
    public static void initialization()
    {
        //System.setErr(System.out);
        System.out.println("initialization");
        try
        {
            Configuration myConfiguration = new
                 Configuration();

            myConfiguration.addClass(Owner.class);
            myConfiguration.addClass(Artifact.class);

            // This is the code that updates the database to
            // the current schema.
            new SchemaUpdate(myConfiguration).execute(true,
                true);

            // Sets up the session factory (used in the rest
            // of the application).
            sessionFactory =
                 myConfiguration.buildSessionFactory();

        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

Listing 3.16 shows the creation of a set of objects, along with the establishment of the relationships between various objects. Note that nowhere is the ownership table referenced by name; the relationships are instead managed by Hibernate. For more information on the management of relationships by Hibernate, see Chapter 7.

Listing 3.16. Creating Objects
    public static void createObjects()
    {
        System.out.println();
        System.out.println("createObjects");

        Session hibernateSession = null;
        Transaction myTransaction = null;
        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction =
                 hibernateSession.beginTransaction();

            Owner myExhibition = new Exhibition();
            myExhibition.setName("New Acquisitions 2005");

            Person myPerson = new Person();
            myPerson.setName("Smith, Bob");

            Foundation myFoundation = new Foundation();
            myFoundation.setName("Smith Foundation");
            myFoundation.setOwner(myPerson);

            Museum myMuseum = new Museum();
            myMuseum.setName("Waldendorf");
            myMuseum.setDateOpened(new java.util.Date());

            hibernateSession.save(myPerson);
            hibernateSession.save(myFoundation);
            hibernateSession.save(myMuseum);
            hibernateSession.flush();
            myTransaction.commit();

            myTransaction = hibernateSession.beginTransaction
                 ();

            for (int i = 0; i < artifactNames.length; i++)
            {
                Artifact myArtifact = new Artifact();
                myArtifact.setTitle(artifactNames[i]);
                hibernateSession.save(myArtifact);

                // Important to issue the save first,
                // so the ID of the artifact is set.
                myArtifact.addOwner(myExhibition);
                myArtifact.addOwner(myFoundation);
                myArtifact.addOwner(myMuseum);

                hibernateSession.save(myExhibition);
                hibernateSession.save(myFoundation);
                hibernateSession.save(myMuseum);

                hibernateSession.flush();
            }

            myTransaction.commit();
        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                hibernateSession.close();
            } catch (Exception e2)
            {
                // Silent failure of session close
            }
        }
    }

Listing 3.17 shows the use of the Criteria API to fetch both the Artifact and all of the associated Owners with a single SQL statement. For more information on the Criteria API, see Chapter 8.

Listing 3.17. Loading the Artifacts and Owners
    public static void loadAllArtifacts()
    {
        System.out.println();
        System.out.println("loadAllArtifacts");

        Session hibernateSession = null;
        Transaction myTransaction = null;

        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction =
                 hibernateSession.beginTransaction();

            // In this example, we use the Criteria API.
            // We could also have used the HQL, but the
            // Criteria API allows us to express this
            // query more easily. First indicate that
            // we want to grab all of the artifacts.
            Criteria query =
                hibernateSession.createCriteria(Artifact.class);

            // Now, specify sorting by the artifact title
            query.addOrder(Order.asc("title"));

            // Indicate that we want to grab all of the
            // associated owners of artifacts as well.
            // This lets us pull of the data in a single
            // SQL statement!
            query.setFetchMode("owners", FetchMode.EAGER);

            // This actually performs the database request,
            // based on the query we've built.
            java.util.Iterator results =
                 query.list().iterator();
                      Artifact myArtifact;

            // Because we are grabbing all of the artifacts and
            // artifact owners, we need to store the returned
            // artifacts

            java.util.LinkedList retrievedArtifacts =
                new java.util.LinkedList();
            while (results.hasNext())
            {
                // Note that the result set is cast to the
                // Animal object directlyno manual
                // binding required.
                myArtifact = (Artifact)results.next();
                if (!retrievedArtifacts.contains(myArtifact))
                    retrievedArtifacts.add(myArtifact);

                update_id = myArtifact.getId();
            }

            java.util.Iterator results2 =
                retrievedArtifacts.iterator();
            while (results2.hasNext())
            {
                myArtifact = (Artifact)results2.next();
                if (false)
                {
                    System.out.println(myArtifact.getId() + "");
                    System.out.println(myArtifact.getTitle() +
                         "");
                }
                java.util.Set myOwners =
                    myArtifact.getOwners();
                java.util.Iterator myOwnersIterator =
                    myOwners.iterator();
                if (false)
                    while (myOwnersIterator.hasNext())
                        System.out.println(
                            ((Owner)myOwnersIterator.next())
                                .getName());
            }

            myTransaction.commit();
        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                if (hibernateSession != null)
                    hibernateSession.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }
    }

Listing 3.18 shows a single object, loaded and then updated after a minor change.

Listing 3.18. Updating a Single Object
    public static void updateOneObject()
    {
        System.out.println();
        System.out.println("updateOneObject");

        Session hibernateSession = null;
        Transaction myTransaction = null;

        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction = hibernateSession.beginTransaction();

            Artifact myArtifact =
                (Artifact)hibernateSession.get(
                    Artifact.class,
                    new Long(update_id));

            myArtifact.setTitle("Test");
            hibernateSession.update(myArtifact);

            myTransaction.commit();

        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                if (hibernateSession != null)
                    hibernateSession.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }
    }

Listing 3.19 shows the deletion of a set of objects that meet a particular HQL query (in this case, items that happen to have a title starting with "Golden").

Note the commented-out call to Session.find() prior to the Session.delete(). Whenever you are deleting objects, it's a good idea to test this out in advance, making sure that the objects being deleted are the objects you actually want to delete.

Listing 3.19. Deleting Particular Objects
    public static void deleteObjects()
    {
        System.out.println();
        System.out.println("deleteObjects");

        Session hibernateSession = null;
        Transaction myTransaction = null;
        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction =
                 hibernateSession.beginTransaction();

            String hql =
                "from Artifact as artifact where "
                    + "artifact.title like 'Golden%'";

            java.util.List myArtifacts =
                 hibernateSession.find(hql);

            hibernateSession.delete(hql);

            hibernateSession.flush();

            String sql =
         "DELETE ownership FROM ownership LEFT JOIN artifact "
         + "ON ownership.artifact_id=artifact.id "
         + "WHERE artifact.id IS NULL";

            Connection myConnection =
                 hibernateSession.connection();
            Statement myStatement =
                 myConnection.createStatement();
            System.out.println(myStatement.execute(sql));
            System.out.println(myStatement.getUpdateCount());
            myTransaction.commit();

        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                if (hibernateSession != null)
                    hibernateSession.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }
    }

You may sometimes wish to perform SQL operations on the database directly, instead of relying on HQL or the Criteria API. This is especially true when performing a mass insert, but Listing 3.20 shows the use of SQL to perform a bulk deletion.

Listing 3.20. Deleting Many Objects at Once Using SQL
    public static void massDelete()
    {
        System.out.println();
        System.out.println("massDelete");
        Session hibernateSession = null;
        Transaction myTransaction = null;

        try
        {
            hibernateSession = sessionFactory.openSession();
            myTransaction =
                 hibernateSession.beginTransaction();
            Connection myConnection =
                 hibernateSession.connection();
            Statement myStatement =
                 myConnection.createStatement();

            String sql = "delete from artifact";
            System.out.println(sql);
            myStatement.execute(sql);

            sql = "delete from owner";
            System.out.println(sql);
            myStatement.execute(sql);

            sql = "delete from ownership";
            System.out.println(sql);
            myStatement.execute(sql);
            myTransaction.commit();

        } catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                myTransaction.rollback();
            } catch (Exception e2)
            {
                // Silent failure of transaction rollback
            }
        } finally
        {
            try
            {
                if (hibernateSession != null)
                    hibernateSession.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }

    }

}

Assuming that everything is working properly, the output of this test application should be as shown in Listing 3.21.

NOTE

The final step of this program is the deletion of all the data in the tablesyou may wish to comment out the references to the deleteObjects() and/or mass Delete() methods in the main() method to explore the data generated in the database.


Listing 3.21. Successful Output
Current count: 0
initialization OK

createObjects

Current count: 5
createObjects OK

loadAllArtifacts

Current count: 5
loadAllArtifacts OK

updateOneObject

Current count: 5
updateOneObject OK

deleteObjects
false
3

Current count: 4
deleteObjects OK

massDelete
delete from artifact
delete from owner
delete from ownership

Current count: 0
massDelete OK