spring orm что это
По следам Spring Pet Clinic. Maven/ Spring Context/ Spring Test/ Spring ORM/ Spring Data JPA
Здравствуйте!
Spring MVC, согласно обзору инструментов и технологий Java за 2014 г. от RevbelLabs, является самым популярным веб фреймворком.
Далее тот же обзор называет лидера ORM — Hibernate и лидера веб-контейнеров — Apache Tomcat. Добавим сюда самую используемую java script библиотеку jQuery, самый популярный css фреймворк Bootstrap, до сих пор самую популярную (несморя на наступление Gradle) инструмент сборки Maven, абсолютный лидер среди тестовый фреймворков JUnit и получим пример приложения на Spring от его создателей:
Spring Pet Clinic (демо приложение).
Кроме перечисленного, в этот достаточно несложный по функциональности проект влючены также Spring-Jdbc, Spring-ORM,
Spring Data JPA,
Hibernate Validator,
SLF4J,
Json Jackson,
JSP,
JSTL,
WebJars,
Dandelion DataTables,
HSQLDB,
Hamcrest,
Mockito и десятки других зависимостей.
Прогресс в разработке ПО подразумевает сокращение объема собственного кода приложения, в идеале, только до бизнес логики приложения.
Однако это дается не бесплатно — количество зависимостей даже для простого проекта перевалило за полсотни (в PetClinic в WEB-INF\lib находится 61 jar).
Конечно не объязательно знать их все, некоторые jar подтягиваются в фоне, и мы даже не подозреваем о них, пока не посмотрим на готовый war или не
выполним mvn project-info-reports:dependencies (в IDEA: Show Dependencies… на проекте Maven). Но с основными приходится работать. И на борьбу с
некоторыми их особенностями иногда тратятся часы, а то и дни. А еще приходится сталкиваться с багами самих фреймворков…
Недавно, вдохновленный Pet Clinic, при создании вебинара по этим технологиям я сделал приложение «Todo Management List»: управление списоком дел
с авторизацией и регистрацией пользователей. К зависимостям Pet Clinic добавились еще Spring Security/ совсем свежий Spring Security
Test и
плагины к jQuery Jeditable и jQuery notification.
Объем статьи не позволяет описать шаги создания приложения (вебинар по созданию приложения занимает 30 часов),
поэтому здесь делюсь ресурсами, некоторыми мыслями и решениями, пришедшими в процессе его создания.
На PaaS Heroku можно найти демо приложения (первый
раз при запуске возможна долгая загрузка и ошибка сервера, повторить).
Примеры приложений
Spring namespace configuration
В конфигурировании Spring есть тенденция прятать детали реализации под свои пространства имен.
Конфигурация становится меньше и понятнее, однако процесс кастомизации или дебага становится не совсем тривиальный: сначала нужно найти бины,
где это реализовано.
Сравните например инициализацию
базы:
Особенно это видно при сравнении бывшего Acegi Security cо Spring Security (все фильтры спрятаны под namespace security).
@Transactional в тестах
В тестах Spring принято использовать транзакционность: после выполнения каждого теста происходит rollback базы в исходное состояние.
Однако сам @Transactional сильно влияет на поведение тестов: например, вы забыли в сервисе/репозитории @Transactional, тест прошел, а приложение упало.
Еще хуже, когда в тесте достаются для сравнения сущности из базы:
они попадают в тот же транзакционный контекст и поведение тестируемых методов становится несколько другим (спасает только evict или detach).
Состояние базы при дебаге теста также не отображается, пока не закончилась транзакция теста.
Более честно использовать инициализатор базы перед каждым тестом:
Обновление: в Spring 4.1 появилась аннотация, заменяющая DbPopulator:
Настройка EntityManagerFactory
Привыкнув в Spring 3.0 к багам о необъявленной в persistence.xml сущности был удивлен, что все работает без этого!
После некоторого копания в коде увидел, что весь target/classes сканируется на entity анотации. Также порадовала возможность конфигурировать JPA без persistence.xml.
Можно задавать конкретные пакеты для сканирования модели, конфигурировать специфичные для провайдера и общие JPA параметры.
Причем их можно вынести в общий db.properties файл:
Выбор реализации пула коннектов.
Spring Data JPA
Привыкнув в каждом проекте создавать собственный AbstractDAO, параметризированный сущностью и ключем с имплементацией основных CRUD на основе EntityManager был обрадован,
что наконец-то он вошел в Spring, правда, в проект Spring Data JPA:
JpaRepository
Он наследуется от более общего CrudRepository
из Spring Data Commons.
Работа с JPA репозиториями сначала поражает: достаточно написать
и метод сам заработает без единой строчки имплементации!
Если JpaRepository и сгенерированных методов недостаточно, можно писать собственную имплементацию методов или запросы Query.
В @Query можно писать JPQL запросы (которые генерятся в @NamedQuery ), а можно ссылаться на уже объявленные @NamedQuery в сущностях (почему то в PetClinic @NamedQuery
игнорируются, хотя такие запросы строятся и проверяются на этапе деплоя).
Например, метод
ссылается на объявленный в User @NamedQuery
В отличии от void CrudRepository.delete(ID id) он возвратит количество модифицированных записей.
Напоследок: ресурсы по темам
Spring
Maven
Логгирование
Персистентность
Если статья понравится, буду готовить часть 2 с неуместившимися Spring MVC, Spring Security, Jackson и пр.
Спасибо за внимание, будет интересно услышать ваше мнение по затронутым темам.
Spring + Hibernate для новичков
Вместо дисклеймера
Что такое ORM?
Ни одно современное веб-приложение не обходится без хранения огромного количества различной информации. Эту задачу обычно возлагают на специальные программы — Систему Управления Базами Данных СУБД. По схеме организации базы данных делятся на несколько видов, и так сложилось, что самым распространенным видом оказались реляционные.
В реляционных базах, данные организованны в виде сущностный (таблиц) и связей между ними. Программисты, работающие с объектно-ориентированными языками программирования, зачастую сталкиваются с задачей преобразования данных из формы, понятной СУБД в привычную объектную форму. Почти всегда решение этих задач занимает огромное количество времени и заставляет писать такие конструкции:
И это только один SELECT, а ведь нужно еще и организовать правильное подключение к СУБД и обеспечить нормальную одновременную работу нескольких пользователей.
Облегчить жизнь программистам и освободить нас от рутины призвана технология Object-Relational Mapping (ORM), которую реализует популярная библиотека Hibernate. Hibernate берет на себя задачу преобразования данных их реляционного вида в объектный, для чтения, и из объектного вида в реляционный — для записи. Кроме того, библиотека позволяет легко настроить подключение к СУБД и с помощью нее очень легко управлять транзакциями.
Быстрый старт
Сейчас мы попробуем с помощью с помощью Hibernate создать отображение в объектную форму вот такой таблицы, которая используется для хранения сессий:
Создадим Bean SessionBean. Бин — это класс, у которого есть констурктор без параметров, конструктор со всеми параметрами и определены get- и set- методы для всех полей.
Также создадим DAO (Data Access Object) — специальный класс, который будет обеспечивать для нас операции чтения и записи в базу данных
После чего становится очень просто извлекать, редактировать и добавлять данные в БД.
На этом закончим знакомство с ORM. В следующих статьях мы рассмотрим наиболее интересные тонкости работы с этой технологией, а также приёмы тестирования баз данных.
Spring ORM и Hibernate
Spring облегчает использование Hibernate в приложениях,беря на себя создание объектов Hibernate и управление ими. Кроме того, Spring позволяет разделить конфигурацию Hibernate от конфигурации базы данных и конфигурации пула соединений.
Подготовка
Нам понадобится пустой maven проект с Spring, Spring ORM, H2, Hibernate и библиотеками тестирования:
1.4.190
Настройка Hibernate
Конфигурация Hibernate традиционно располагается в файле hibernate.cfg.xml В моём примере я использую H2 в качестве базы данных:
name = «hibernate.hbm2ddl.auto» > update
name = «hibernate.dialect» > org.hibernate.dialect.H2Dialect
name = «hibernate.connection.url» > jdbc:h2:mem:test
Настройка Spring
Для включения поддержки Hibernate в Spring необходимо добавить в контекст особый бин. Можно сделать это программно, а можно с использованием xml конфигурации:
name = «configLocation» value = «hibernate.cfg.xml» />
Свойство configLocation указывает на имя и расположение файла конфигурации Hibernate.
Вместо настройки базы в конфигурации hibernate можно использовать Spring для разделения настроек соединения, пула соединений и Hibernate:
name = «driverClassName» value = «org.h2.Driver» />
name = «url» value = «dbc:h2:mem:test» />
name = «dataSource» ref = «h2» />
В примере выше создаётся пул соединений DBCP к базе H2, который передаётся в конфигурацию Hibernate.
Схема данных
ORM отображает объектную модель данных на реляционную модель данных. Чтобы не загораживать пример, используем как можно более простую модель:
Аннотация @Entity говорит Hibernate, что это класс сущности, а @Getter и @Setter генерируют код для доступа к полям.
Уровень DAO
Хорошим тоном разработки является разделение кода, который работает непосредственно с базами данных (уровень DAO), от кода, который обрабатывает данные (уровень сервисов). Это позволяет абстрагировать сервисы от конкретной реализации DAO и, при необходимости, менять эти реализации без изменения кода сервисов.
Spring orm что это
The Spring Framework supports integration with Hibernate, Java Persistence API (JPA), Java Data Objects (JDO) and iBATIS SQL Maps for resource management, data access object (DAO) implementations, and transaction strategies. For example, for Hibernate there is first-class support with several convenient IoC features that address many typical Hibernate integration issues. You can configure all of the supported features for O/R (object relational) mapping tools through Dependency Injection. They can participate in Spring’s resource and transaction management, and they comply with Spring’s generic transaction and DAO exception hierarchies. The recommended integration style is to code DAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Spring’s DAO templates is no longer recommended; however, coverage of this style can be found in the Section A.1, “Classic ORM usage” in the appendices.
Spring adds significant enhancements to the ORM layer of your choice when you create data access applications. You can leverage as much of the integration support as you wish, and you should compare this integration effort with the cost and risk of building a similar infrastructure in-house. You can use much of the ORM support as you would a library, regardless of technology, because everything is designed as a set of reusable JavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thus most examples in this section show configuration inside a Spring container.
Benefits of using the Spring Framework to create your ORM DAOs include:
Easier testing. Spring’s IoC approach makes it easy to swap the implementations and configuration locations of Hibernate SessionFactory instances, JDBC DataSource instances, transaction managers, and mapped object implementations (if needed). This in turn makes it much easier to test each piece of persistence-related code in isolation.
Common data access exceptions. Spring can wrap exceptions from your ORM tool, converting them from proprietary (potentially checked) exceptions to a common runtime DataAccessException hierarchy. This feature allows you to handle most persistence exceptions, which are non-recoverable, only in the appropriate layers, without annoying boilerplate catches, throws, and exception declarations. You can still trap and handle exceptions as necessary. Remember that JDBC exceptions (including DB-specific dialects) are also converted to the same hierarchy, meaning that you can perform some operations with JDBC within a consistent programming model.
Integrated transaction management. You can wrap your ORM code with a declarative, aspect-oriented programming (AOP) style method interceptor either through the @Transactional annotation or by explicitly configuring the transaction AOP advice in an XML configuration file. In both cases, transaction semantics and exception handling (rollback, and so on) are handled for you. As discussed below, in Resource and transaction management, you can also swap various transaction managers, without affecting your ORM-related code. For example, you can swap between local transactions and JTA, with the same full services (such as declarative transactions) available in both scenarios. Additionally, JDBC-related code can fully integrate transactionally with the code you use to do ORM. This is useful for data access that is not suitable for ORM, such as batch processing and BLOB streaming, which still need to share common transactions with ORM operations.
TODO: provide links to current samples
13.2 General ORM integration considerations
This section highlights considerations that apply to all ORM technologies. The Section 13.3, “Hibernate” section provides more details and also show these features and configurations in a concrete context.
The major goal of Spring’s ORM integration is clear application layering, with any data access and transaction technology, and for loose coupling of application objects. No more business service dependencies on the data access or transaction strategy, no more hard-coded resource lookups, no more hard-to-replace singletons, no more custom service registries. One simple and consistent approach to wiring up application objects, keeping them as reusable and free from container dependencies as possible. All the individual data access features are usable on their own but integrate nicely with Spring’s application context concept, providing XML-based configuration and cross-referencing of plain JavaBean instances that need not be Spring-aware. In a typical Spring application, many important objects are JavaBeans: data access templates, data access objects, transaction managers, business services that use the data access objects and transaction managers, web view resolvers, web controllers that use the business services,and so on.
13.2.1 Resource and transaction management
Typical business applications are cluttered with repetitive resource management code. Many projects try to invent their own solutions, sometimes sacrificing proper handling of failures for programming convenience. Spring advocates simple solutions for proper resource handling, namely IoC through templating in the case of JDBC and applying AOP interceptors for the ORM technologies.
The infrastructure provides proper resource handling and appropriate conversion of specific API exceptions to an unchecked infrastructure exception hierarchy. Spring introduces a DAO exception hierarchy, applicable to any data access strategy. For direct JDBC, the JdbcTemplate class mentioned in a previous section provides connection handling and proper conversion of SQLException to the DataAccessException hierarchy, including translation of database-specific SQL error codes to meaningful exception classes. For ORM technologies, see the next section for how to get the same exception translation benefits.
When it comes to transaction management, the JdbcTemplate class hooks in to the Spring transaction support and supports both JTA and JDBC transactions, through respective Spring transaction managers. For the supported ORM technologies Spring offers Hibernate, JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well as JTA support. For details on transaction support, see the Chapter 10, Transaction Management chapter.
13.2.2 Exception translation
The postprocessor automatically looks for all exception translators (implementations of the PersistenceExceptionTranslator interface) and advises all beans marked with the @Repository annotation so that the discovered translators can intercept and apply the appropriate translation on the thrown exceptions.
In summary: you can implement DAOs based on the plain persistence technology’s API and annotations, while still benefiting from Spring-managed transactions, dependency injection, and transparent exception conversion (if desired) to Spring’s custom exception hierarchies.
13.3 Hibernate
We will start with a coverage of Hibernate 3 in a Spring environment, using it to demonstrate the approach that Spring takes towards integrating O/R mappers. This section will cover many issues in detail and show different variations of DAO implementations and transaction demarcation. Most of these patterns can be directly translated to all other supported ORM tools. The following sections in this chapter will then cover the other ORM technologies, showing briefer examples there.
As of Spring 3.0, Spring requires Hibernate 3.2 or later.
13.3.1 SessionFactory setup in a Spring container
To avoid tying application objects to hard-coded resource lookups, you can define resources such as a JDBC DataSource or a Hibernate SessionFactory as beans in the Spring container. Application objects that need to access resources receive references to such predefined instances through bean references, as illustrated in the DAO definition in the next section.
The following excerpt from an XML application context definition shows how to set up a JDBC DataSource and a Hibernate SessionFactory on top of it:
Switching from a local Jakarta Commons DBCP BasicDataSource to a JNDI-located DataSource (usually managed by an application server) is just a matter of configuration:
13.3.2 Implementing DAOs based on plain Hibernate 3 API
Hibernate 3 has a feature called contextual sessions, wherein Hibernate itself manages one current Session per transaction. This is roughly equivalent to Spring’s synchronization of one Hibernate Session per transaction. A corresponding DAO implementation resembles the following example, based on the plain Hibernate API:
This style is similar to that of the Hibernate reference documentation and examples, except for holding the SessionFactory in an instance variable. We strongly recommend such an instance-based setup over the old-school static HibernateUtil class from Hibernate’s CaveatEmptor sample application. (In general, do not keep any resources in static variables unless absolutely necessary.)
The main advantage of this DAO style is that it depends on Hibernate API only; no import of any Spring class is required. This is of course appealing from a non-invasiveness perspective, and will no doubt feel more natural to Hibernate developers.
In summary: you can implement DAOs based on the plain Hibernate 3 API, while still being able to participate in Spring-managed transactions.
13.3.3 Declarative transaction demarcation
We recommend that you use Spring’s declarative transaction support, which enables you to replace explicit transaction demarcation API calls in your Java code with an AOP transaction interceptor. This transaction interceptor can be configured in a Spring container using either Java annotations or XML.This declarative transaction capability allows you to keep business services free of repetitive transaction demarcation code and to focus on adding business logic, which is the real value of your application.
Prior to continuing, you are strongly encouraged to read Section 10.5, “Declarative transaction management” if you have not done so.
Furthermore, transaction semantics like propagation behavior and isolation level can be changed in a configuration file and do not affect the business service implementations.
The following example shows how you can configure an AOP transaction interceptor, using XML, for a simple service class:
This is the service class that is advised:
We also show an attribute-support based configuration, in the following example. You annotate the service layer with @Transactional annotations and instruct the Spring container to find these annotations and provide transactional semantics for these annotated methods.
As you can see from the following configuration example, the configuration is much simplified, compared to the XML example above, while still providing the same functionality driven by the annotations in the service layer code. All you need to provide is the TransactionManager implementation and a » » entry.
13.3.4 Programmatic transaction demarcation
Spring’s TransactionInterceptor allows any checked application exception to be thrown with the callback code, while TransactionTemplate is restricted to unchecked exceptions within the callback. TransactionTemplate triggers a rollback in case of an unchecked application exception, or if the transaction is marked rollback-only by the application (via TransactionStatus ). TransactionInterceptor behaves the same way by default but allows configurable rollback policies per method.
13.3.5 Transaction management strategies
For distributed transactions across multiple Hibernate session factories, simply combine JtaTransactionManager as a transaction strategy with multiple LocalSessionFactoryBean definitions. Each DAO then gets one specific SessionFactory reference passed into its corresponding bean property. If all underlying JDBC data sources are transactional container ones, a business service can demarcate transactions across any number of DAOs and any number of session factories without special regard, as long as it is using JtaTransactionManager as the strategy.
Both HibernateTransactionManager and JtaTransactionManager allow for proper JVM-level cache handling with Hibernate, without container-specific transaction manager lookup or a JCA connector (if you are not using EJB to initiate transactions).
13.3.6 Comparing container-managed and locally defined resources
Spring’s transaction support is not bound to a container. Configured with any strategy other than JTA, transaction support also works in a stand-alone or test environment. Especially in the typical case of single-database transactions, Spring’s single-resource local transaction support is a lightweight and powerful alternative to JTA. When you use local EJB stateless session beans to drive transactions, you depend both on an EJB container and JTA, even if you access only a single database, and only use stateless session beans to provide declarative transactions through container-managed transactions. Also, direct use of JTA programmatically requires a Java EE environment as well. JTA does not involve only container dependencies in terms of JTA itself and of JNDI DataSource instances. For non-Spring, JTA-driven Hibernate transactions, you have to use the Hibernate JCA connector, or extra Hibernate transaction code with the TransactionManagerLookup configured for proper JVM-level caching.
Spring-driven transactions can work as well with a locally defined Hibernate SessionFactory as they do with a local JDBC DataSource if they are accessing a single database. Thus you only have to use Spring’s JTA transaction strategy when you have distributed transaction requirements. A JCA connector requires container-specific deployment steps, and obviously JCA support in the first place. This configuration requires more work than deploying a simple web application with local resource definitions and Spring-driven transactions. Also, you often need the Enterprise Edition of your container if you are using, for example, WebLogic Express, which does not provide JCA. A Spring application with local resources and transactions spanning one single database works in any Java EE web container (without JTA, JCA, or EJB) such as Tomcat, Resin, or even plain Jetty. Additionally, you can easily reuse such a middle tier in desktop applications or test suites.
13.3.7 Spurious application server warnings with Hibernate
You resolve this warning by simply making Hibernate aware of the JTA PlatformTransactionManager instance, to which it will synchronize (along with Spring). You have two options for doing this:
More likely you do not already have the JTA PlatformTransactionManager instance, because Spring’s JtaTransactionManager can find it itself. Thus you need to configure Hibernate to look up JTA PlatformTransactionManager directly. You do this by configuring an application server- specific TransactionManagerLookup class in the Hibernate configuration, as described in the Hibernate manual.
The JTA transaction commits.
Spring’s JtaTransactionManager is synchronized to the JTA transaction, so it is called back through an afterCompletion callback by the JTA transaction manager.
Among other activities, this synchronization can trigger a callback by Spring to Hibernate, through Hibernate’s afterTransactionCompletion callback (used to clear the Hibernate cache), followed by an explicit close() call on the Hibernate Session, which causes Hibernate to attempt to close() the JDBC Connection.
In some environments, this Connection.close() call then triggers the warning or error, as the application server no longer considers the Connection usable at all, because the transaction has already been committed.
the JTA transaction is ready to commit.
Spring’s JtaTransactionManager is synchronized to the JTA transaction, so the transaction is called back through a beforeCompletion callback by the JTA transaction manager.
Spring is aware that Hibernate itself is synchronized to the JTA transaction, and behaves differently than in the previous scenario. Assuming the Hibernate Session needs to be closed at all, Spring will close it now.
The JTA transaction commits.
Hibernate is synchronized to the JTA transaction, so the transaction is called back through an afterCompletion callback by the JTA transaction manager, and can properly clear its cache.
13.4 JDO
Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following the same style as the Hibernate support. The corresponding integration classes reside in the org.springframework.orm.jdo package.
13.4.1 PersistenceManagerFactory setup
Spring provides a LocalPersistenceManagerFactoryBean class that allows you to define a local JDO PersistenceManagerFactory within a Spring application context:
13.4.2 Implementing DAOs based on the plain JDO API
Because the above DAO follows the dependency injection pattern, it fits nicely into a Spring container, just as it would if coded against Spring’s JdoTemplate :
If your data access code always runs within an active transaction (or at least within active transaction synchronization), it is safe to omit the PersistenceManager.close() call and thus the entire finally block, which you might do to keep your DAO implementations concise:
With such DAOs that rely on active transactions, it is recommended that you enforce active transactions through turning off TransactionAwarePersistenceManagerFactoryProxy ‘s allowCreate flag:
The main advantage of this DAO style is that it depends on JDO API only; no import of any Spring class is required. This is of course appealing from a non-invasiveness perspective, and might feel more natural to JDO developers.
However, the DAO throws plain JDOException (which is unchecked, so does not have to be declared or caught), which means that callers can only treat exceptions as fatal, unless you want to depend on JDO’s own exception structure. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly JDO-based and/or do not need any special exception treatment.
13.4.3 Transaction management
You are strongly encouraged to read Section 10.5, “Declarative transaction management” if you have not done so, to get a more detailed coverage of Spring’s declarative transaction support.
To execute service operations within transactions, you can use Spring’s common declarative transaction facilities. For example:
13.4.4 JdoDialect
As an advanced feature, both JdoTemplate and JdoTransactionManager support a custom JdoDialect that can be passed into the jdoDialect bean property. In this scenario, the DAOs will not receive a PersistenceManagerFactory reference but rather a full JdoTemplate instance (for example, passed into the jdoTemplate property of JdoDaoSupport ). Using a JdoDialect implementation, you can enable advanced features supported by Spring, usually in a vendor-specific manner:
Applying specific transaction semantics such as custom isolation level or transaction timeout
Retrieving the transactional JDBC Connection for exposure to JDBC-based DAOs
Applying query timeouts, which are automatically calculated from Spring-managed transaction timeouts
Eagerly flushing a PersistenceManager, to make transactional changes visible to JDBC-based data access code
Advanced translation of JDOExceptions to Spring DataAccessExceptions
See the JdoDialect Javadoc for more details on its operations and how to use them within Spring’s JDO support.
13.5 JPA
The Spring JPA, available under the org.springframework.orm.jpa package, offers comprehensive support for the Java Persistence API in a similar manner to the integration with Hibernate or JDO, while being aware of the underlying implementation in order to provide additional features.
13.5.1 Three options for JPA setup in a Spring environment
The Spring JPA support offers three ways of setting up the JPA EntityManagerFactory that will be used by the application to obtain an entity manager.
13.5.1.1 LocalEntityManagerFactoryBean
Only use this option in simple deployment environments such as stand-alone applications and integration tests.
The LocalEntityManagerFactoryBean creates an EntityManagerFactory suitable for simple deployment environments where the application uses only JPA for data access. The factory bean uses the JPA PersistenceProvider autodetection mechanism (according to JPA’s Java SE bootstrapping) and, in most cases, requires you to specify only the persistence unit name:
This form of JPA deployment is the simplest and the most limited. You cannot refer to an existing JDBC DataSource bean definition and no support for global transactions exists. Furthermore, weaving (byte-code transformation) of persistent classes is provider-specific, often requiring a specific JVM agent to specified on startup. This option is sufficient only for stand-alone applications and test environments, for which the JPA specification is designed.
13.5.1.2 Obtaining an EntityManagerFactory from JNDI
Use this option when deploying to a Java EE 5 server. Check your server’s documentation on how to deploy a custom JPA provider into your server, allowing for a different provider than the server’s default.
Obtaining an EntityManagerFactory from JNDI (for example in a Java EE 5 environment), is simply a matter of changing the XML configuration:
This action assumes standard Java EE 5 bootstrapping: the Java EE server autodetects persistence units (in effect, META-INF/persistence.xml files in application jars) and persistence-unit-ref entries in the Java EE deployment descriptor (for example, web.xml ) and defines environment naming context locations for those persistence units.
If multiple persistence units are used in the same application, the bean names of such JNDI-retrieved persistence units should match the persistence unit names that the application uses to refer to them, for example, in @PersistenceUnit and @PersistenceContext annotations.
13.5.1.3 LocalContainerEntityManagerFactoryBean
Use this option for full JPA capabilities in a Spring-based application environment. This includes web containers such as Tomcat as well as stand-alone applications and integration tests with sophisticated persistence requirements.
The following example shows a typical persistence.xml file:
The exclude-unlisted-classes element always indicates that no scanning for annotated entity classes is supposed to occur, in order to support the shortcut. This is in line with the JPA specification, which suggests that shortcut, but unfortunately is in conflict with the JPA XSD, which implies false for that shortcut. Consequently, false is not supported. Simply omit the exclude-unlisted-classes element if you want entity class scanning to occur.
This option may conflict with the built-in JPA capabilities of a Java EE 5 server. In a full Java EE 5 environment, consider obtaining your EntityManagerFactory from JNDI. Alternatively, specify a custom persistenceXmlLocation on your LocalContainerEntityManagerFactoryBean definition, for example, META-INF/my-persistence.xml, and only include a descriptor with that name in your application jar files. Because the Java EE 5 server only looks for default META-INF/persistence.xml files, it ignores such custom persistence units and hence avoid conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, for example.)
When is load-time weaving required?
Not all JPA providers require a JVM agent ; Hibernate is an example of one that does not. If your provider does not require an agent or you have other alternatives, such as applying enhancements at build time through a custom compiler or an ant task, the load-time weaver should not be used.
The LoadTimeWeaver interface is a Spring-provided class that allows JPA ClassTransformer instances to be plugged in a specific manner, depending whether the environment is a web container or application server. Hooking ClassTransformers through a Java 5 agent typically is not efficient. The agents work against the entire virtual machine and inspect every class that is loaded, which is usually undesirable in a production server environment.
Spring provides a number of LoadTimeWeaver implementations for various environments, allowing ClassTransformer instances to be applied only per class loader and not per VM.
Refer to Section 7.8.4.5, “Spring configuration” in the AOP chapter for more insight regarding the LoadTimeWeaver implementations and their setup, either generic or customized to various platforms (such as Tomcat, WebLogic, OC4J, GlassFish, Resin and JBoss).
As described in the aforementioned section, you can configure a context-wide LoadTimeWeaver using the context:load-time-weaver configuration element. (This has been available since Spring 2.5.) Such a global weaver is picked up by all JPA LocalContainerEntityManagerFactoryBeans automatically. This is the preferred way of setting up a load-time weaver, delivering autodetection of the platform (WebLogic, OC4J, GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver to all weaver-aware beans:
However, if needed, one can manually specify a dedicated weaver through the loadTimeWeaver property:
No matter how the LTW is configured, using this technique, JPA applications relying on instrumentation can run in the target platform (ex: Tomcat) without needing an agent. This is important especially when the hosting applications rely on different JPA implementations because the JPA transformers are applied only at class loader level and thus are isolated from each other.
13.5.1.4 Dealing with multiple persistence units
For applications that rely on multiple persistence units locations, stored in various JARS in the classpath, for example, Spring offers the PersistenceUnitManager to act as a central repository and to avoid the persistence units discovery process, which can be expensive. The default implementation allows multiple locations to be specified that are parsed and later retrieved through the persistence unit name. (By default, the classpath is searched for META-INF/persistence.xml files.)
13.5.2 Implementing DAOs based on plain JPA
The DAO above has no dependency on Spring and still fits nicely into a Spring application context. Moreover, the DAO takes advantage of annotations to require the injection of the default EntityManagerFactory :
As an alternative to defining a PersistenceAnnotationBeanPostProcessor explicitly, consider using the Spring context:annotation-config XML element in your application context configuration. Doing so automatically registers all Spring standard post-processors for annotation-based configuration, including CommonAnnotationBeanPostProcessor and so on.
The main problem with such a DAO is that it always creates a new EntityManager through the factory. You can avoid this by requesting a transactional EntityManager (also called «shared EntityManager» because it is a shared, thread-safe proxy for the actual transactional EntityManager) to be injected instead of the factory:
Method- and field-level Injection
What about class-level annotations?
On the Java EE 5 platform, they are used for dependency declaration and not for resource injection.
The main advantage of this DAO style is that it only depends on Java Persistence API; no import of any Spring class is required. Moreover, as the JPA annotations are understood, the injections are applied automatically by the Spring container. This is appealing from a non-invasiveness perspective, and might feel more natural to JPA developers.
13.5.3 Transaction Management
You are strongly encouraged to read Section 10.5, “Declarative transaction management” if you have not done so, to get a more detailed coverage of Spring’s declarative transaction support.
To execute service operations within transactions, you can use Spring’s common declarative transaction facilities. For example:
13.5.4 JpaDialect
Applying specific transaction semantics such as custom isolation level or transaction timeout)
Retrieving the transactional JDBC Connection for exposure to JDBC-based DAOs)
Advanced translation of PersistenceExceptions to Spring DataAccessExceptions
This is particularly valuable for special transaction semantics and for advanced translation of exception. The default implementation used ( DefaultJpaDialect ) does not provide any special capabilities and if the above features are required, you have to specify the appropriate dialect.
See the JpaDialect Javadoc for more details of its operations and how they are used within Spring’s JPA support.
13.6 iBATIS SQL Maps
The iBATIS support in the Spring Framework much resembles the JDBC support in that it supports the same template style programming, and as with JDBC and other ORM technologies, the iBATIS support works with Spring’s exception hierarchy and lets you enjoy Spring’s IoC features.
Spring supports iBATIS 2.x. The iBATIS 1.x support classes are no longer provided.
13.6.1 Setting up the SqlMapClient
To map this Account class with iBATIS 2.x we need to create the following SQL map Account.xml :
The configuration file for iBATIS 2 looks like this:
Remember that iBATIS loads resources from the class path, so be sure to add the Account.xml file to the class path.
13.6.2 Using SqlMapClientTemplate and SqlMapClientDaoSupport
In the DAO, we use the pre-configured SqlMapClientTemplate to execute the queries, after setting up the SqlMapAccountDao in the application context and wiring it with our SqlMapClient instance:
An SqlMapTemplate instance can also be created manually, passing in the SqlMapClient as constructor argument. The SqlMapClientDaoSupport base class simply preinitializes a SqlMapClientTemplate instance for us.
The SqlMapClientTemplate offers a generic execute method, taking a custom SqlMapClientCallback implementation as argument. This can, for example, be used for batching:
In general, any combination of operations offered by the native SqlMapExecutor API can be used in such a callback. Any thrown SQLException is converted automatically to Spring’s generic DataAccessException hierarchy.