• 沒有找到結果。

Using Hibernate Annotations

在文檔中 Praise for the First Edition (頁 103-107)

This chapter covers

2.2 Starting a Java Persistence project

2.2.1 Using Hibernate Annotations

Let’s first use Hibernate Annotations to replace the Hibernate XML mapping files with inline metadata. You may want to copy your existing “Hello World” project directory before you make the following changes—you’ll migrate from native Hibernate to standard JPA mappings (and program code later on).

Copy the Hibernate Annotations libraries to your WORKDIR/lib directory—see the Hibernate Annotations documentation for a list of required libraries. (At the time of writing, hibernate-annotations.jar and the API stubs in ejb3-persistence.jar were required.)

Now delete the src/hello/Message.hbm.xml file. You’ll replace this file with annotations in the src/hello/Message.java class source, as shown in listing 2.10.

package hello;

import javax.persistence.*;

@Entity

@Table(name = "MESSAGES") public class Message { @Id @GeneratedValue

@Column(name = "MESSAGE_ID") private Long id;

@Column(name = "MESSAGE_TEXT") private String text;

@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "NEXT_MESSAGE_ID") private Message nextMessage;

private Message() {}

public Message(String text) { this.text = text;

}

public Long getId() { return id;

}

private void setId(Long id) { this.id = id;

}

public String getText() { return text;

}

public void setText(String text) { this.text = text;

}

public Message getNextMessage() { return nextMessage;

}

public void setNextMessage(Message nextMessage) { this.nextMessage = nextMessage;

} }

The first thing you’ll probably notice in this updated business class is the import of the javax.persistence interfaces. Inside this package are all the standardized JPA annotations you need to map the @Entity class to a database @Table. You put

Listing 2.10 Mapping the Message class with annotations

annotations on the private fields of the class, starting with @Id and @Generated-Value for the database identifier mapping. The JPA persistence provider detects that the @Id annotation is on a field and assumes that it should access properties on an object directly through fields at runtime. If you placed the @Id annotation on the getId() method, you’d enable access to properties through getter and set-ter methods by default. Hence, all other annotations are also placed on either fields or getter methods, following the selected strategy.

Note that the @Table, @Column, and @JoinColumn annotations aren’t necessary.

All properties of an entity are automatically considered persistent, with default strategies and table/column names. You add them here for clarity and to get the same results as with the XML mapping file. Compare the two mapping metadata strategies now, and you’ll see that annotations are much more convenient and reduce the lines of metadata significantly. Annotations are also type-safe, they sup-port autocompletion in your IDE as you type (like any other Java interfaces), and they make refactoring of classes and properties easier.

If you’re worried that the import of the JPA interfaces will bind your code to this package, you should know that it’s only required on your classpath when the annotations are used by Hibernate at runtime. You can load and execute this class without the JPA interfaces on your classpath as long as you don’t want to load and store instances with Hibernate.

A second concern that developers new to annotations sometimes have relates to the inclusion of configuration metadata in Java source code. By definition, config-uration metadata is metadata that can change for each deployment of the applica-tion, such as table names. JPA has a simple solution: You can override or replace all annotated metadata with XML metadata files. Later in the book, we’ll show you how this is done.

Let’s assume that this is all you want from JPA—annotations instead of XML. You don’t want to use the JPA programming interfaces or query language; you’ll use Hibernate Session and HQL. The only other change you need to make to your project, besides deleting the now obsolete XML mapping file, is a change in the Hibernate configuration, in hibernate.cfg.xml:

<!DOCTYPE hibernate-configuration SYSTEM

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<!-- ... Many property settings ... -->

<!-- List of annotated classes-->

<mapping class="hello.Message"/>

</session-factory>

</hibernate-configuration>

The Hibernate configuration file previously had a list of all XML mapping files.

This has been replaced with a list of all annotated classes. If you use programmatic configuration of a SessionFactory, the addAnnotatedClass() method replaces the addResource() method:

// Load settings from hibernate.properties

AnnotationConfiguration cfg = new AnnotationConfiguration();

// ... set other configuration options programmatically cfg.addAnnotatedClass(hello.Message.class);

SessionFactory sessionFactory = cfg.buildSessionFactory();

Note that you have now used AnnotationConfiguration instead of the basic Hibernate Configuration interface—this extension understands annotated classes. At a minimum, you also need to change your initializer in HibernateUtil to use that interface. If you export the database schema with an Ant target, replace

<configuration> with <annotationconfiguration> in your build.xml file.

This is all you need to change to run the “Hello World” application with anno-tations. Try running it again, probably with a fresh database.

Annotation metadata can also be global, although you don’t need this for the

“Hello World” application. Global annotation metadata is placed in a file named package-info.java in a particular package directory. In addition to listing anno-tated classes, you need to add the packages that contain global metadata to your configuration. For example, in a Hibernate XML configuration file, you need to add the following:

<!DOCTYPE hibernate-configuration SYSTEM

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<!-- ... Many property settings ... -->

<!-- List of annotated classes-->

<mapping class="hello.Message"/>

<!-- List of packages with package-info.java -->

<mapping package="hello"/>

</session-factory>

</hibernate-configuration>

Or you could achieve the same results with programmatic configuration:

// Load settings from hibernate.properties

AnnotationConfiguration cfg = new AnnotationConfiguration();

// ... set other configuration options programmatically cfg.addClass(hello.Message.class);

cfg.addPackage("hello");

SessionFactory sessionFactory = cfg.buildSessionFactory();

Let’s take this one step further and replace the native Hibernate code that loads and stores messages with code that uses JPA. With Hibernate Annotations and Hibernate EntityManager, you can create portable and standards-compliant map-pings and data access code.

在文檔中 Praise for the First Edition (頁 103-107)