Статьи

Учебник: Hibernate, JPA и Spring MVC — часть 2

Из этого туториала вы узнаете, как взять базовое приложение Hibernate / JPA, преобразовать его в веб-проект Spring MVC, чтобы иметь возможность просматривать базу данных в веб-браузере, и, наконец, использовать аннотацию Spring @Transactional для сокращения кода на платформе.

В этом руководстве предполагается, что вы знакомы с Java и Maven, и что вы завершили первую часть этого руководства . Вам также нужно будет загрузить и установить Tomcat.

Вы можете проверить код только что из Github .

Контейнер Управляемый источник данных

Есть ряд ключевых файлов, которые нам нужно изменить или создать, чтобы преобразовать код из первой части в веб-проект. Первое, что нам нужно сделать (при условии, что у вас установлен Tomcat и установлен CATALINA_HOME в среде вашего компьютера), это перенести конфигурацию JDBC на Tomcat так, чтобы источником данных управлял Tomcat, а не программно, и можно получить доступ с помощью JNDI.

Для этого добавьте следующие строки в элемент GlobalNamingResources файла $ CATALINA_HOME / conf / server.xml:

1
2
3
4
5
6
<Resource auth='Container'
    driverClassName='org.apache.derby.jdbc.EmbeddedDriver'
    maxActive='8' maxIdle='4'
    name='jdbc/tutorialDS' type='javax.sql.DataSource'
    url='jdbc:derby:tutorialDB;create=true'
    username='' password='' />

Jar-файл, содержащий org.apache.derby.jdbc.EmbeddedDriver, должен быть доступен для Tomcat. Быстрый способ получить банку из локального репозитория Maven, например, ~ / .m2 / репозиторий / org / apache / derby / derby / 10.4.1.3 / derby-10.4.1.3.jar. Скопируйте этот файл в $ CATALINA_HOME / lib и перезапустите Tomcat, чтобы убедиться в отсутствии ошибок.

Эти изменения создадут источник данных, к которому могут получить доступ развернутые приложения. В Tomcat 7 вы можете просматривать управляемые ресурсы по адресу http: // localhost: 8080 / manager / text / resources ; вы должны увидеть что-то вроде:

1
2
3
OK - Listed global resources of all types
jdbc/tutorialDS:org.apache.tomcat.dbcp.dbcp.BasicDataSource
UserDatabase:org.apache.catalina.users.MemoryUserDatabase

Преобразование в веб-проект

Используя какой-то проект из первой части, нам нужно внести следующие изменения:

Нам нужно изменить проект для создания веб-архива, поэтому в файл pom.xml добавьте следующее:

1
<packaging>war</packaging>

Вы захотите добавить (для удобства) строку внутри секции сборки, которая создает .war без версии проекта:

1
<finalName>${project.artifactId}</finalName>

Нам также нужны библиотеки API сервлетов:
<Зависимость>

1
2
3
4
5
     <groupId>javax.servlet</groupId>
     <artifactId>servlet-api</artifactId>
     <version>2.5</version>
     <scope>provided</scope>
</dependency>

Примечание: область действия этого «предоставлена», поскольку Tomcat уже имеет встроенную библиотеку сервлетов.

Чтобы источник данных был доступен приложению, создайте файл src / main / webapp / META-INF / context.xml со следующими строками:

1
2
3
<Context>
    <ResourceLink global='jdbc/tutorialDS' name='jdbc/tutorialDS' type='javax.sql.DataSource'/>
</Context>

Это делает источник данных, управляемый Tomcat, доступным для нашего приложения. Нам также нужна заглушка для src / main / webapp / WEB-INF / web.xml:

1
2
3
4
5
6
<web-app
    version='2.5'>
</web-app>

Скомпилируйте и разверните приложение в Tomcat. Вы не сможете ничего увидеть в этот момент, так как нет никаких сервлетов или страниц.

Maven может создать и развернуть для вас Maven, или вы можете запустить Tomcat в большинстве IDE. Есть много статей об этом в другом месте, поэтому я не буду освещать это здесь.

Добавление Spring MVC

Мы собираемся использовать Spring MVC для этого, поэтому нам нужны некоторые дополнительные изменения для поддержки этого:

Добавьте следующую зависимость в ваш pom.xml:

1
2
3
4
5
<dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-webmvc</artifactId>
           <version>3.0.6.RELEASE</version>
       </dependency>

Мы хотим указать Tomcat использовать Spring для отправки запросов, поэтому нам нужно добавить следующие строки в наш web.xml:
<Контекстно-пары>

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
 
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
 
<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>

Это перенаправит все запросы на страницы, оканчивающиеся на «.html», в Spring, и Spring выберет соответствующий контроллер для обслуживания каждого запроса. Нам также нужно создать контекст приложения для сервлетов Spring, и он должен находиться в src / main / webapp / WEB-INF / mvc-dispatcher-servlet.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version='1.0' encoding='UTF-8'?>
    '>
 
    <context:component-scan base-package='tutorial'/>
    <context:annotation-config/>
 
    <bean class='org.springframework.web.servlet.view.InternalResourceViewResolver'>
        <property name='prefix'><value>/WEB-INF/pages/</value></property>
        <property name='suffix'><value>.jsp</value></property>
    </bean>
 
</beans>

Этот XML делает две вещи:

  1. Он говорит Spring сканировать классы в пакете ‘tutorial’ и ниже для классов, аннотированных как bean-компоненты.
  2. Как преобразовать имя представления в его ресурс. По сути, он говорит: «возьми имя, добавь префикс« / WEB-INF / pages », а затем добавь суффикс« .jsp ».

Вы могли бы хотеть повторно развернуть это, чтобы курить проверить это.

Чтобы проверить это, нам нужно отобразить страницу. Первая страница будет отображать список всех пользователей. Нам понадобятся два файла; Первый — это контроллер, который обслуживает запросы:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package tutorial;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
public class UsersController {
 
    @RequestMapping('/users')
    public String users(Model model) {
        return 'users';
    }
}

Второй элемент — это страница для отображения. Это основано на строке, возвращаемой UsersController.users (), и, используя правила для распознавателя ресурсов, мы знаем, что этот файл должен быть WEB-INF / pages / users.jsp. Создайте заглушку страницы, что-то вроде:

1
2
3
4
5
<html>
<body>
<h1>Users</h1>
</body>
</html>

Наконец, вы можете проверить это путем повторного развертывания в Tomcat и использования браузера для просмотра http: // localhost: 8080 / tutorial-hibernate-jpa / users.html .

Добавление Spring ORM

Spring содержит поддержку для внедрения менеджеров сущностей в bean-компоненты, и для этого требуется добавить всего несколько строк кода в ваши pom.xml и mvc-dispatcher-context.xml:

1
2
3
4
5
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>3.0.6.RELEASE</version>
</dependency>
1
2
3
4
5
<jee:jndi-lookup id='tutorialDS' jndi-name='java:/comp/env/jdbc/tutorialDS' expected-type='javax.sql.DataSource'/>
 
<bean id='entityManagerFactory' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
     <property name='dataSource' ref='tutorialDS'/>
 </bean>

Элемент ‘jndi-lookup’ создает компонент из ресурса JNDI, и он используется фабрикой менеджера сущностей для создания менеджеров сущностей. Другие объекты JNDI также могут быть найдены таким же образом.

Примечание: вам нужно добавить пространство имен XML и XSD к корневому элементу: xmlns: jee = ‘http: //www.springframework.org/schema/jee.’

Наконец, мы можем добавить код для добавления менеджера сущностей в наш контроллер и получения пользователей из базы данных.

01
02
03
04
05
06
07
08
09
10
11
12
13
public class UsersController {
 
    @PersistenceContext
    private EntityManager entityManager;
 
    @RequestMapping('/users')
    public String users(Model model) {
 
        model.addAttribute('users', entityManager.createQuery('select u from User u').getResultList());
 
        return 'users';
    }
}

Этот код использует диспетчер сущностей для получения всех пользователей и связывает его с атрибутом «пользователи», который будет виден нашим JSP.

Мы хотим показать пользователей на странице. Для этого я буду использовать JSTL; Вы можете использовать другую технологию, если хотите, но я быстро предоставлю вам все необходимое, если нет. Опять же, есть много хороших руководств по JSTL, если вы не знакомы. Во-первых, добавьте еще одну зависимость для вас pom.xml:

1
2
3
4
5
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

И обновление users.html отображает пользователей:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %>
<html>
<body>
<h1>Users</h1>
<table>
    <thead><tr><td>ID</td><td>Name</td></tr></thead>
    <tbody>
        <c:forEach var='user' items='${users}'>
        <tr><td>${user.id}</td><td>${user.name}</td></tr>
        </c:forEach>
    </tbody>
</table>
</body>
</html>

Наконец, вы можете проверить это в своем браузере.

@Transactional

Последний кусок головоломки — создание пользователя. Для этого нам понадобится базовая форма, например, я создал pages / create-user.jsp:

1
2
3
4
5
6
7
8
9
<html>
<body>
<h1>Create User</h1>
<form method='post'>
Name: <input name='name'/>
<input type='submit'/>
</form>
</body>
</html>

Нам нужен контроллер для доступа к этому, поэтому добавьте это в UsersController:

1
2
3
4
@RequestMapping(value = '/create-user', method = RequestMethod.GET)
public <a href="https://www.google.com/search?hl=en&q=allinurl%3Astring+java.sun.com&btnI=I%27m%20Feeling%20Lucky">String</a> createUser(Model model) {
    return 'create-user';
}

Обратите внимание: этот метод принимает только запросы GET. Когда мы разместим форму, нам понадобится другой метод. Вы можете проверить это, повторно развернув Tomcat и перейдя по адресу http: // localhost: 8080 / tutorial-hibernate-jpa / create-user.html . Вы заметите, что отправка страницы приводит к ошибке HTTP 405. Мы можем обслуживать POST-запросы следующим (перегруженным) методом:

01
02
03
04
05
06
07
08
09
10
11
@RequestMapping(value = '/create-user', method = RequestMethod.POST)
@Transactional
public String createUser(Model model, String name) {
 
    User user = new User();
    user.setName(name);
 
    entityManager.persist(user);
 
    return 'redirect:/users.html';
}

Мы использовали аннотацию @Transactional здесь. Когда мы сделаем это, Spring создаст прокси-объект для нашего компонента и будет управлять транзакцией за нас, начиная, фиксируя и откатывая при возникновении ошибок. Это намного меньше кода (одна строка против дюжины) и безопаснее (меньше шансов на опечатку), чем мы сами открываем и закрываем транзакцию. Вы можете увидеть пример кода для подробной версии в этом посте . Мы должны сказать Spring для поддержки этого, добавив следующие строки в наш контекст Spring: указание использовать транзакции на основе аннотаций и какой компонент должен управлять транзакциями:

1
2
3
4
5
<tx:annotation-driven/>
 
<bean id='transactionManager' class='org.springframework.orm.jpa.JpaTransactionManager'>
    <property name='entityManagerFactory' ref='entityManagerFactory' />
</bean>

Примечание: вам нужно добавить правильную схему и в документ:

Вы можете проверить это, перейдя на страницу и отправив нового пользователя. После этого вы будете перенаправлены на страницу пользователей, где сможете увидеть своего нового пользователя.

Вывод

В этом примере XML-строк больше, чем Java, но большая часть XML является одноразовой, и вы увидите, что по мере увеличения размера вашего приложения это соотношение уменьшается. Вы можете использовать Spring для поддержки объектов JPA, упрощая миграцию в / из JEE.

Я рассмотрел только части «C» и «R» CRUD, здесь у вас должно быть достаточно информации, чтобы попробовать все остальное самостоятельно.

Код для этого на Github . Hibernate Java Maven ORM Spring Framework

Ссылка: Учебное пособие: Hibernate, JPA и Spring MVC — часть 2 от нашего партнера по JCG Алекса Коллинза в блоге Алекса Коллинза .