Skip to main content
main-content

Über dieses Buch

Persistence is an important set of techniques and technologies for accessing and transacting data, and ensuring that data is mobile regardless of specific applications and contexts. In Java development, persistence is a key factor in enterprise, e-commerce, and other transaction-oriented applications.

Today, the Spring framework is the leading out-of-the-box solution for enterprise Java developers; in it, you can find a number of Java Persistence solutions.

This book gets you rolling with fundamental Spring Framework 3 concepts and integrating persistence functionality into enterprise Java applications using Hibernate, the Java™ Persistence API (JPA) 2, and the Grails Object Relational Mapping tool, GORM.

Covers core Hibernate fundamentals, demonstrating how the framework can be best utilized within a Spring application context Covers how to use and integrate JPA 2, found in the new Java EE 6 platform Covers how to integrate and use the new Grails persistence engine, GORM

Inhaltsverzeichnis

Frontmatter

Chapter 1. Architecting Your Application with Spring, Hibernate, and Patterns

Throughout this book, we will demonstrate how Spring integrates with key persistence frameworks and strategies. Along the way, you will learn more about Spring’s features and capabilities, and some of the key design patterns it uses to get the job done effectively. Until several years ago, simple Java Database Connectivity (JDBC) was one of the most popular choices for implementing an application’s persistence tier. However, EJB and open source ORM frameworks such as Hibernate have significantly changed the persistence landscape, by allowing developers to focus on a Java-based domain model, maintaining the object-oriented semantics of Java while still working with the relational concepts of a SQL database. ORM offers a level of abstraction that affords increased flexibility by decoupling application code from the lower-level details of a relational database.
However, things aren’t always as easy as they seem. ORM is not without its drawbacks and consequences. First, as we mentioned earlier, there is the impedance mismatch between the object-oriented Java world and the relational SQL world. ORM frameworks, such as Hibernate, do their best to address this mismatch by offering extensive options for mapping between SQL and Java. Nevertheless, fundamental differences between these two spheres will always exist, and therefore can’t be fully addressed.
Despite some of these limitations, ORM frameworks offer unparalleled benefits by streamlining the way in which developers work with a relational database. For instance, Hibernate introduces ancillary features, such as caching and lazy loading, which can improve the performance of an application dramatically with little or no additional coding effort. Hibernate and JPA also provide tools to seamlessly generate database schemas and even keep them in sync with the Java-based domain model. These features make the integration between application code and database even more seamless—to the point that it is often possible to forget that you are using a database altogether!
With an IoC container at its core, Spring helps to reduce application complexity, as well as coupling between classes, by handling the details necessary to integrate one dependency with another. Spring also provides transactional behavior, AOP capability, and infrastructural classes for numerous persistence frameworks, such as Hibernate and JPA.
Hibernate is an ORM framework intended to translate between relational databases and the realm of object-oriented development. Hibernate provides a querying interface, using Hibernate Query Language (HQL) or the Hibernate Criteria API. Together, Spring and Hibernate are a dynamic duo, capable of simplifying dependency collaboration, reducing coupling, and providing abstractions over persistence operations.
JPA is a Java standard for persistence, the design of which was significantly influenced by the Hibernate developers. Hibernate can be used as an implementation provider for JPA, allowing you to adhere to standards and gain framework portability, while still utilizing the excellent Hibernate implementation. However, there are some useful features that are not available in JPA, but are present only in the Hibernate implementation. With the release of JPA 2.0, many of the limitations of the JPA spec have been addressed, bringing more parity to Hibernate and JPA. For instance, JPA 2.0 now provides a Criteria API for querying in an object-oriented manner, and compile-time checking. In this chapter, we outlined the foundational layers of a typical persistence tier, which is composed of the domain model, the DAO layer, and the service facade. We also discussed some integral design patterns leveraged by the Spring Framework, such as the Template design pattern. Although adhering to the typical foundational layers for your persistence tier is usually the best approach, some newer frameworks follow slightly different strategies, such as using the Active-Record pattern.
In the next chapter, we will build on the concepts and patterns introduced in this chapter as we incrementally build a Gallery application using Spring and Hibernate. Over the course of this book, it is our aim to illustrate time-tested and pragmatic best practices that we hope you will be able to use in your own applications as well.
Before we start coding, it’s important to understand some of the core Spring and Hibernate concepts. So in the next chapter you will learn about Spring’s architecture and capabilities, such as dependency injection, AOP, and persistence-related features.
Paul Tepper Fisher, Brian D. Murphy

Chapter 2. Spring Basics

In this chapter, you’ve learned about the fundamental concepts that power the Spring Framework. You saw how to bootstrap a Spring ApplicationContext, learned the basics of configuring bean dependencies in Spring XML configuration files, and developed an understanding of bean scopes and life cycles. The benefits of dependency injection are now clear. You can effectively delegate to the Spring container to manage and resolve your application dependencies, and doing so can help keep your application’s dependencies loosely coupled. Finally, you were given a glimpse into the power of managing orthogonal coding concerns with AOP. Throughout the rest of this book, we will build on the Spring concepts introduced in this chapter to define and implement an art gallery application.
Paul Tepper Fisher, Brian D. Murphy

Chapter 3. Basic Application Setup

In this chapter, you have gotten a sense for what is involved in setting up a web application using core Spring, Maven, a database, and Spring MVC.
Maven is a great tool that development teams can use to simplify day-to-day development. You can manage your dependencies, ensuring repeatable build processes, and provide a consistent interface for developers on your team to use for interacting with your project.
You’ve also learned about some of Spring’s features, including component scanning, BeanFactoryPostProcessors like the PropertPlaceholderConfigurer, Spring’s namespace support, and more advanced XML configuration management with import declarations. Component scanning is likely the most important of these features, since it allows Spring to locate classes within a specified package structure so that it can manage these components and resolve dependencies appropriately.
The component-scanning feature allows developers to use annotations as hints for Spring. It simplifies the work required to wire dependencies together and even reduces the amount of XML configuration required. For instance, the @Repository annotation should be used to indicate those classes that compose the DAO layer, the @Service annotation can be used to designate those classes that are part of an application’s service façade, and the @Controller annotation denotes the presence of a POJO that should be used for Spring MVC interactions. These annotations simplify the definition of the respective tiers, imbuing layer classes with metadata that helps describe their purpose.
You also saw what’s required to integrate a database into a Spring application using the Apache commons-dbcp library for connection pools or via JNDI if you want to use the datasource offerings from your application container.
In the next chapters, we’ll build out our domain model and integrate Hibernate into our art gallery application.
Paul Tepper Fisher, Brian D. Murphy

Chapter 4. Persistence with Hibernate

Frameworks like Spring and Hibernate provided a means to solve some complex enterprise challenges. The critical difference between EJB 2.0 and frameworks like Spring and Hibernate is that this complexity is an option that you can elect to utilize, rather than an integral component of the framework architecture that you are forced to embrace.
In this chapter, you took a stroll down memory lane to see how persistence has evolved in the Java ecosystem, and now have a firmer understanding of the terminology as well as the distinctions between specifications and implementations. You’ve learned that you can have an application that uses many permutations of specifications and implementations. For instance, you can build a single application that uses EJB 3.0 for a distributed component-based architecture, with JPA for persistence powered by Hibernate as the JPA implementation. You also got a feel for the domain model and DAO structure that underpins our art gallery example application. Finally, you learned quite a lot about setting up a JPA application in a Spring environment. You are now armed with enough information to get a JPA application working.
In the next chapter, we’ll continue building the domain model for our art gallery application.
Paul Tepper Fisher, Brian D. Murphy

Chapter 5. Domain Model Fundamentals

In this chapter, we’ve introduced the fundamentals for defining a domain model with Hibernate. You learned about the mapping process and how you can use annotations to provide Hibernate with the appropriate clues to effectively map your object-oriented domain classes to your relational database.
We also examined association mapping, differentiating between the various cardinality options Hibernate provides. These details—such as whether to use many-to-many or one-to-many associations—have a significant impact on your domain model design, as well as the resultant database schema. Furthermore, it is important to think carefully about whether an association should be unidirectional or bidirectional. While bidirectional associations are often necessary to simplify reference walking and access, this option can have consequences in terms of circular dependencies that may complicate marshaling implementations.
Hibernate provides a powerful feature called cascading that allows you to associate the operations applied to one entity with its children entities so that these operations cascade. This feature is useful for ensuring that child entities are kept in sync with the state and life cycle of their parent entities.
Paul Tepper Fisher, Brian D. Murphy

Chapter 6. DAOs and Querying

In this chapter, we introduced some core ORM concepts, and you learned more about how Spring and Hibernate can be used together. We also reviewed some key design patterns that are instrumental to the way in which Spring integrates with many persistence frameworks. Through our gallery application examples, we demonstrated how to implement an effective DAO layer. We examined several options for integrating Hibernate—using the HibernateTemplate as well as using the Hibernate Core APIs.
The DAO pattern is considered a best practice for abstracting persistence-related functionality. Using Hibernate, we demonstrated how to load entities via their identifier, save or update individual entities, and query for domain objects using HQL. We discussed some querying techniques and examined various approaches for performing joins, using both implicit and explicit forms. We also contrasted implementation strategies using Spring’s HibernateTemplate and Hibernate Core APIs. Although HibernateTemplate has played a significant role in both Spring and Hibernate’s history, its use is becoming less important due to improvements to the Hibernate architecture after version 3.0.1.
This chapter discussed several implementation options for building our gallery application’s DAO layer. We built on some of the concepts introduced in the previous chapter, which illustrated mapping strategies for our application’s domain model. In the next chapter, we will build on the DAO layer introduced in this chapter, demonstrating how the service layer can be used to define an application’s transactional business logic.
Paul Tepper Fisher, Brian D. Murphy

Chapter 7. Transaction Management

In this chapter, you’ve learned both the fundamentals and low-level details for managing database transactions with Spring. We’ve explored two different avenues for applying transactions declaratively with Spring: via annotation and through XML-based Spring configuration. It’s also possible to utilize Spring’s transaction management programmatically, through the use of the TransactionTemplate. However this approach couples transactional behavior with the application’s business logic.
Understanding how transactions work, along with the available configuration options, is critical for developing and debugging multiuser applications. We’ve discussed both simple and complex scenarios in this chapter, and we hope they give you a taste of what’s possible when using Spring for transaction management.
Most important, Spring provides a consistent approach for applying transactional semantics to an application, no matter what the architecture or environment. This means that you can configure and code your application the same way, regardless of whether you’re deploying to a JEE app server using a JTA datasource or to a lightweight container with a local datasource. The difference is just a matter of configuration.
Paul Tepper Fisher, Brian D. Murphy

Chapter 8. Effective Testing

This chapter introduced some testing strategies for Spring applications. Of course, you can do a lot more to test with both JUnit and Spring, not to mention the really powerful testing constructs that are made possible by the mocking frameworks we mentioned. Also, topics such as performance testing and load testing are extremely relevant to persistence.
For more advanced integration testing with databases, we recommend you check out the DbUnit JUnit extension. DbUnit provides excellent facilities for ensuring that your database is in a known state in between tests, as well as tooling to aid in assembling fixture data that can be used across an entire suite of tests.
Paul Tepper Fisher, Brian D. Murphy

Chapter 9. Best Practices and Advanced Techniques

In this chapter, we examined several strategies for evaluating and improving application performance. One of the most common pitfalls for Hibernate developers is the N+1 selects issue. This problem typically stems from a failure to properly tune a domain object’s mapping configuration or the queries within the DAO layer. Understanding how this problem can appear, as well as how to detect it, is important in ensuring decent ORM performance. Although tuning really depends on the unique requirements of an application, often the best solution is to consider what data needs to be made available within the service, controller, or view layers, and optimize your queries to load this data as efficiently as possible. You saw that using a fetch-join is often an effective approach for initializing an association without requiring multiple queries. Relying on Hibernate’s batching capability can also be a decent strategy, although it isn’t always as effective.
Another technique for improving performance is to leverage Hibernate’s caching capabilities. Properly tuning the cache can make a dramatic difference for application performance. However, caching can also degrade performance if it is not done correctly. For example, caching too aggressively can trigger OutOfMemoryException exceptions. Understanding the different caching configuration options within Hibernate will help you select the appropriate behavior. It is also important to experiment with different TTL settings.
Hibernate provides several different caching layers. The first-level cache is scoped at the EntityManager, but rarely requires much tuning. The second-level cache provides the ability to cache domain objects, collections, and queries. Each of these cache types is managed and cached separately. Domain objects are keyed by their identifier, and the values of all an object’s properties are persisted to the cache. Associations and queries, however, persist only collections of identifiers. These identifiers are cross-referenced against the entity cache to load the actual domain object data.
Some cache implementations, such as Ehcache, are clusterable, allowing updates to the cache to be persisted to other nodes in the cluster. However, without a way to keep the caches of other nodes within the cluster in sync, there is the potential for significant problems, caused by version conflicts or stale data. For instance, it is possible for an important update applied to the database to be inadvertently rolled back. This can happen when a node’s cache is not notified of the initial update to the database. Then, when a different user attempts to perform a write operation on the same entity, the user is applying his updates against stale data, which effectively rolls back the initial update once the second (stale) process is applied.
When deploying a clustered application, it is important to use a clusterable cache or a centralized cache server that all the nodes in the cluster can share. Ehcache provides a stand-alone server product called Cache Server. Additionally, Ehcache offers several configurable options for tuning its clusterable features. It is important to experiment with various settings to determine the options most suitable for your application’s requirements.
In the next chapter, we will continue to investigate advanced strategies for providing specialized features for your persistence tier, improving performance, and utilizing best practices.
Paul Tepper Fisher, Brian D. Murphy

Chapter 10. Integration Frameworks

In this chapter, we’ve demonstrated how to integrate and extend Hibernate in order to implement more advanced application features. We discussed some of the challenges with exposing RESTful web services on Hibernate-powered applications, and how to simplify a serialization or marshaling strategy. We examined Spring 3’s new MVC capabilities, as well as its OXM abstraction for providing object-to-XML marshaling.
We also discussed the DTO pattern, and how this strategy can reduce the complexities of serializing your domain model. However, translating a domain class to a DTO class (and back again) can be a source of defects and maintenance problems. One solution is to use a framework like Dozer. Dozer handles the mapping between two different classes, using convention over configuration and mapping configuration files. By abstracting these translation details to a specialized framework, the complexities inherent in a DTO mapping layer are significantly reduced.
Providing full-text search capability is a very important and common requirement for many applications. Lucene is an open source Java framework that offers powerful indexing and search capability, but can be difficult to integrate into an application without requiring significant glue code to sync changes to the domain model with the Lucene index. Hibernate Search is a framework that bridges the gap between these two excellent frameworks, enhancing key Hibernate framework classes to offer Lucene querying and indexing capabilities. Hibernate Search allows developers to execute Lucene queries within the realm of Hibernate, so that search results return standard Hibernate entities.
Spring and Hibernate are amazing open source frameworks. However, building upon the foundations of these tools is the key to successful application development. Learning best practices for integrating your persistence tier with other frameworks is as important as learning the persistence framework itself.
Paul Tepper Fisher, Brian D. Murphy

Chapter 11. GORM and Grails

In this chapter, we’ve covered some of the fundamentals for developing a web application using Groovy and Grails. Grails provides an interesting contrast to the topics covered in the previous chapters. Although based firmly on Spring and Hibernate, Grails utilizes Active Record as an alternative to the DAO design pattern. This approach is more practical in Grails due to its use of the dynamic language Groovy, allowing new behavior and methods to be dynamically defined. Through the use of convention-over-configuration, Grails can significantly reduce the amount of effort required to get a working application up and running.
Despite some of these differences, Spring’s profound influence is clearly present, and most of the lessons and patterns utilized with other persistence frameworks can still be applied to Grails. You’ve seen how some of the fundamental Spring concepts, such as dependency injection, can be further enhanced through Groovy-based configuration and implicit, convention-based wiring.
Paul Tepper Fisher, Brian D. Murphy

Chapter 12. Spring Roo

As you’ve seen in this chapter, although Roo isn’t yet magical enough to put programmers out of work, it does give you an enormous jump-start in terms of raw development speed. It helps eliminate much of the tedium associated with developing enterprise Java applications by automatically generating boilerplate code into AspectJ ITDs and modifying your Spring application context configuration as your project grows.
Roo boasts a strong architecture based on OSGi and add-ons. With the backing of SpringSource, it’s likely to evolve at a frantic pace as the Roo team strives to deliver more best-of-breed solutions that simplify the lives of developers around the globe.
One of the biggest hurdles for adopting most RAD frameworks on the JVM is that using them is a viable option only when writing a new application or in the rare circumstance that a total application rewrite is in order. But Roo can be introduced into an existing application without forcing any changes to the way other team members write their code. As the framework is proven in your environment, the productivity gains should be irrefutable, and your development team will likely embrace the positive change. We highly recommend that you try using it to implement a new feature on your existing Spring- and Hibernate-powered application.
Paul Tepper Fisher, Brian D. Murphy

Backmatter

Weitere Informationen

Premium Partner

BranchenIndex Online

Die B2B-Firmensuche für Industrie und Wirtschaft: Kostenfrei in Firmenprofilen nach Lieferanten, Herstellern, Dienstleistern und Händlern recherchieren.

Whitepaper

- ANZEIGE -

Best Practices für die Mitarbeiter-Partizipation in der Produktentwicklung

Unternehmen haben das Innovationspotenzial der eigenen Mitarbeiter auch außerhalb der F&E-Abteilung erkannt. Viele Initiativen zur Partizipation scheitern in der Praxis jedoch häufig. Lesen Sie hier  - basierend auf einer qualitativ-explorativen Expertenstudie - mehr über die wesentlichen Problemfelder der mitarbeiterzentrierten Produktentwicklung und profitieren Sie von konkreten Handlungsempfehlungen aus der Praxis.
Jetzt gratis downloaden!

Bildnachweise