Introduction to Hibernate 2http://www.systemmobile.com/?p=11 June 28, 2006 11:33 am A major portion of the development of an enterprise application involves the creation and maintenance of the persistence layer used to store and retrieve objects from the database of choice. Many organizations resort to creating homegrown, often buggy, persistence layers. If changes are made to the underlying database schema, it can be expensive to propagate those changes to the rest of the application. Hibernate steps in to fill this gap, providing an easy-to-use and powerful object-relational persistence framework for Java applications. Hibernate provides support for collections and object relations, as well as composite types. In addition to persisting objects, Hibernate provides a rich query language to retrieve objects from the database, as well as an efficient caching layer and Java Management Extensions (JMX) support. User-defined data types and composite primary keys give additional flexibility to support legacy applications. Hibernate is released under the Lesser GNU Public License, which is sufficient for use in commercial as well as open source applications. It supports numerous databases, including Oracle and DB2, as well as popular open source databases such as PostgreSQL and MySQL. An active user community helps to provide support and tools to extend Hibernate and make using it easier. This article covers Hibernate 2.1, which was released on December 2003. How Hibernate Works Rather than utilize bytecode processing or code generation, Hibernate uses runtime reflection to determine the persistent properties of a class. The objects to be persisted are defined in a mapping document, which serves to describe the persistent fields and associations, as well as any subclasses or proxies of the persistent object. The mapping documents are compiled at application startup time and provide the framework with necessary information for a class. Additionally, they are used in support operations, such as generating the database schema or creating stub Java source files.
The Mapping Documents Our example utilizes two trivial classes, <hibernate-mapping> <class name="example.Team" table="teams"> <id name="id" column="team_id" type="long" unsaved-value="null"> <generator class="hilo"/> </id> <property name="name" column="team_name" type="string" length="15" not-null="true"/> <property name="city" column="city" type="string" length="15" not-null="true"/> <set name="players" cascade="all" inverse="true" lazy="true"> <key column="team_id"/> <one-to-many class="example.Player"/> </set> </class> </hibernate-mapping> <hibernate-mapping> <class name="example.Player" table="players"> <id name="id" column="player_id" type="long" unsaved-value="null"> <generator class="hilo"/> </id> <property name="firstName" column="first_name" type="string" length="12" not-null="true"/> <property name="lastName" column="last_name" type="string" length="15" not-null="true"/> <property name="draftDate" column="draft_date" type="date"/> <property name="annualSalary" column="salary" type="float"/> <property name="jerseyNumber" column="jersey_number" type="integer" length="2" not-null="true"/> <many-to-one name="team" class="example.Team" column="team_id"/> </class> </hibernate-mapping> The mapping documents are reasonably clear, but certain areas warrant explanation. The
The The Our <set name="players" cascade="all" inverse="true" lazy="true"> <key column="team_id"/> <one-to-many class="example.Player"/> </set> Figure 3 defines a set of Two attributes in the The <many-to-one name="team" class="example.Team" column="team_id"/> Figure - bi-directional association from the Player class to the Team class The line shown in above figure will create a bi-directional association from the Hibernate Properties The properties that Hibernate uses to connect to the database and generate the schema are stored in a file called hibernate.connection.username=ralph hibernate.connection.password=nader hibernate.connection.url=jdbc:postgresql://localhost/example hibernate.connection.driver_class=org.postgresql.Driver hibernate.dialect=net.sf.hibernate.dialect.PostgreSQLDialect hibernate.connection.pool_size=3 # optional, see below The first four property values are familiar to any developer that has worked with JDBC. The last property, An additional features to improve database portability are query language substitutions. These substitutions allow the developer to rename SQL functions or tokens using the hibernate.query.substitutions toUpper=UPPER # rename the SQL UPPER() function to 'toUpper()' This feature is useful if your database doesn’t understand boolean TRUE and FALSE values. Hibernate has an internal connection pool, but it is only suitable for testing or experimenting with the framework. For serious development use, Hibernate supports C3P0, Apache DBCP, and Proxool connection pools. Links to these utilities are provided in the Resources section. If your preferred connection pooling framework isn’t yet supported, you may add support for it by implementing the You may also set the The Schema Mapping files in hand, it's time to generate the database schema. Hibernate ships with the SchemaExport utility that will create the schema necessary for the mapping documents. This utility may be run from the command line or from an Ant build script to connect to the database and create the schema, or to export the schema to a file. # from the command line java -cp classpath net.sf.hibernate.tool.hbm2ddl.SchemaExport options mapping_files <!– from an Ant build.xml –> <target name="init-db"> <taskdef classname="net.sf.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="project.class.path" name="schemaexport"/> <schemaexport delimiter=";" drop="false" output="schema.sql" properties="config/hibernate.properties" quiet="false" text="false"> <fileset dir="${build.destdir}"> <include name="**/*.hbm.xml"/> </fileset> </schemaexport> </target> This is what our schema looks like: Figure - generated database schema The The Source Files Rather than create the persistent classes by hand, I've chosen to use the java -cp classpath net.sf.hibernate.tool.hbm2java.CodeGenerator options mapping_files Figure - CodeGenerator usage The generated classes have the following structure (constructors removed from diagram for brevity): Figure - diagram of example classes generated by Hibernate Creating the SessionFactory The Configuration cfg = new Configuration() .addClass(example.Player.class) .addClass(example.Team.class); SessionFactory factory = cfg.buildSessionFactory(); Figure - Configuring and creating a SessionFactory The The Creating and Updating Persistent Classes As far as Hibernate is concerned, classes are either transient or persistent. Transient classes are instances that have not been saved to the database. To make a transient instance persistent, simply save it using the Player player = new Player(); // … populate player object Session session = SessionFactory.openSession(); session.saveOrUpdate(player); Figure - saving persistent objects The To create and save a Team team = new Team(); team.setCity("Detroit"); team.setName("Pistons"); // add a player to the team. Player player = new Player(); player.setFirstName("Chauncey"); player.setLastName("Billups"); player.setJerseyNumber(1); player.setAnnualSalary(4000000f); Set players = new HashSet(); players.add(player); team.setPlayers(players); // open a session and save the team Session session = SessionFactory.openSession(); session.saveOrUpdate(team); This will persist the Unsaved Value Strategies Retrieving Persistent Classes If you know the primary key value of the object that you want to retrieve, you can load it with the // method 1: loading a persistent instance Session session = SessionFactory.createSession(); Player player = session.load(Player.class, playerId); // method 2: loading the Player's state Player player = new Player(); session.load(player, playerId); Figure - Loading persistent instances To retrieve a persistent class without knowing its primary key value, you can use the Named parameters allow you to specify names in the HQL statements instead of question marks as parameter flags. For example:
To set the value of the
HQL is a very rich object query language and, because of its depth, will be the subject of a future article. Deleting Persistent Classes Making a persistent object transient is accomplished with the // method 1 - deleting the Player loaded in figure 12 session.delete(player); // method 2 - deleting all of the Players with a // salary greater than 4 million session.delete("from player in class example.Player where player.annualSalary > 4000000"); Figure - deleting a persistent object It's Collections Hibernate can manage the persistence of object collections, whether they are Sets, Maps, Lists, arrays of objects or primitive values. It also allows another form of collection called a "bag". A bag can be mapped to a Additional semantics supported by implementing classes, such as When accessing a lazily initialized collection, it's important to remember that a Session session = factory.openSession(); Team team = (Team) session.find("from team in class example.Team where team.city = ?", cityName, Hibernate.STRING).get(0); Set players = team.getPlayers(); session.close(); Player p = (Player) players.get(0); // exception will be thrown here Figure - incorrect use of lazy initialization The exception is thrown in Figure 15 because the Performance Considerations Fortunately this functionality doesn't come at much of a performance cost. The Hibernate website claims that its "overhead is much less than 10% of the JDBC calls," and my experience in deploying applications using Hibernate supports this. Hibernate can make multiple optimizations when interacting with the database, including caching objects, efficient outer join fetching and executing SQL statements only when needed. It is difficult to achieve this level of sophistication with hand-coded JDBC. A link to the performance FAQ on the Hibernate website can be found in the Resources section. Alternative Persistence Frameworks Hibernate isn't the only framework available for mapping objects to persistent data stores. I encourage you to evaluate each of them and choose the best one for your needs. Some alternative frameworks, listed in no particular order, are:
Conclusion This article has given you an introduction to what Hibernate can do. Hibernate delivers a high-performance, open source persistence framework comparable to many of its open source and commercial counterparts. Developers utilizing Hibernate can greatly reduce the amount of time and effort needed to code, test, and deploy applications. However, we've only scratched the surface and I encourage you to explore Hibernate for yourself. About the Author Nick Heudecker is a software developer with more than eight years of experience designing and building enterprise applications. His firm, System Mobile, Inc., specializes in application integration, custom software development and wireless applications. He is a Sun Certified Java Programmer and is located in Chicago. Resources
|
'프로그래밍 > Framework' 카테고리의 다른 글
[Struts2] struts.properties (0) | 2009.03.13 |
---|---|
[펌] Spring 2.0과 Ruby(JRuby)의 연동 (0) | 2007.11.28 |
[펌] Hibernate 3.02 Reference Document 한글 버전 (0) | 2007.11.28 |
[펌] ibatis (0) | 2007.11.28 |
[펌] 중복처리 (saveToken() ) 를 일반 form 에서 사용하기 (0) | 2007.11.28 |