Spring MVC, JPA и Hibernate. Настройки JPA и ORM, создание сущностей, выполнение запросов к БД
Подключение ORM (Hibernate) в приложение Spring MVC. Настройки JPA и ORM, создание сущностей, выполнение запросов к БД.
Обзор приложения Spring MVC + AngularJS + Bootstrap + HTML5
Используемые технологии и библиотеки
- Spring MVC 4.2.4.Release
- Hibernate 5.0.1.Final
- Spring Data 1.9.1.Release
- Maven 3.2.5
- IntelliJ IDEA 15.0.2
1. Описание задачи
В продолжении темы об использовании JDBC рассмотрим использование стандарта JPA и его реализации Hibernate 5. Подключим необходимые зависимости для использования JPA в Spring MVC и Hibernate. Создадим несколько сущностей и сделаем простые запросы к базе данных.
Отдельно отмечу, что работа Hibernate и Spring описана в разделе Spring DATA.
2. Структура проекта
Для работы с Hibernate в этой части были добавлены только два класса — ORMController и ORMService. Первый обрабатывает запросы и перенаправляет к сервис классу, который непосредственно работает с базой данных и классами-сущностями. В качестве объектов базы данных используется класс User.
3. Подключение зависимостей pom.xml
Для подключения Hibernate 5 в Spring MVC были добавлены следующие зависимости:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<!-- Hibernate / JPA --> <hibernate.version>5.0.1.Final</hibernate.version> <!-- Spring Data --> <spring-framework.data.version>1.9.1.RELEASE</spring-framework.data.version> <!--Hibernate ORM--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!--Hibernate validator (contains @NotEmpty)--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency> <!--Spring Data--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-framework.data.version}</version> </dependency> |
Непосредственно библиотека Hibernate, вспомогательные классы (например для использования аннотации @NotEmpty), а так же зависимости spring-data.
полный файл pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ru.javastudy</groupId> <artifactId>mvc_html5_angular</artifactId> <version>1.0</version> <properties> <!-- Generic properties --> <java.version>1.8</java.version> <!-- Web --> <jsp.version>2.2</jsp.version> <jstl.version>1.2</jstl.version> <servlet.version>3.1.0</servlet.version> <!-- Spring --> <spring-framework.version>4.2.4.RELEASE</spring-framework.version> <!-- JUnit test --> <junit.version>4.12</junit.version> <!-- Logging --> <!--logback - improved version of log4j--> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.13</slf4j.version> <!-- jackson json JSON Processing API --> <jackson.databind-version>2.2.3</jackson.databind-version> <!-- Hibernate / JPA --> <hibernate.version>5.0.1.Final</hibernate.version> <!-- I don't know why, but with 5.0.5 final app not working! --> <!-- Spring Data --> <spring-framework.data.version>1.9.1.RELEASE</spring-framework.data.version> </properties> <dependencyManagement> <!--all spring dependencies --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring-framework.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--bootstrap webjars.org--> <dependencies> <!-- Spring MVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!-- Other Servlet Web dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!--Servlet API--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- Apache Commons File Upload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- Excel view --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.12</version> </dependency> <!-- PDF view --> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.5</version> </dependency> <!-- HSQLDB embedded database. Встроенная база данных--> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.3.3</version> </dependency> <!-- Spring JDBC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <!--JUnit Test--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Test Artifacts with Spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <!--Contains org.springframework.mail.javamail--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Spring MVC Mail Related Dependency --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <!-- Spring REST jackson JSON Processing API --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.databind-version}</version> </dependency> <!--Hibernate ORM--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!--Hibernate validator (contains @NotEmpty)--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency> <!--Spring Data--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-framework.data.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgument>-Xlint:all</compilerArgument> <showWarnings>true</showWarnings> <showDeprecation>true</showDeprecation> </configuration> </plugin> </plugins> <!--need to find configs in tests in package web-inf like @ContextConfiguration(locations = {"classpath:/config/application-context.xml" --> <testResources> <testResource> <directory>src/main/webapp/WEB-INF/config</directory> </testResource> </testResources> </build> </project> |
4. Настройки Spring MVC для использования ORM
Основные настройки для работы с JPA и Hibernate были записаны в application-context.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd "> <!--find property file. See bean id='dataSource' for example ${jdbc.hsqldb.driverClass}--> <context:property-placeholder location="classpath:util.properties" /> <!-- XML Bean Definitions --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.hsqldb.driverClass}" /> <property name="url" value="${jdbc.hsqldb.url}" /> <property name="username" value="${jdbc.hsqldb.username}" /> <property name="password" value="${jdbc.hsqldb.password}" /> </bean> <!-- initialize Embedded DataSource. Встроенная база данных--> <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:dbschema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:initialize-database> <!--Do not forget activate @Transactional JPA annotation with <annotation-driven/>--> <!-- JPA Persistence Context and EntityManager configuration --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > <!--packagesToScan - search Entity and mapping them --> <property name="packagesToScan" value="ru.javastudy.mvcHtml5Angular.mvc.bean" /> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" > <property name="generateDdl" value="true" /> <property name="showSql" value="true" /> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!-- Automatic Transaction Participation--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> </beans> |
Вначале задается источник данных (dataSource), который в нашем случае является in-memory базой данных H2. Настройки для url, username берутся из файла util.properties (задается строчкой выше <context:property-placeholder location=»classpath:util.properties» />). Главной частью этой статьи является описание бина entityManagerFactory. В свойствах (property) указываются: пакеты для сканирования\поиска сущностей (маппят классы на таблицы); источник данных — dataSource; JPA адаптер — HibernateJpaVendorAdapter и два необязательных свойства (generateDdl и showSql); далее свойства подключения jpa к базе данных (аналогично как это было для ранее рассмотренного случая работы с JDBC). В конце был подключен менеджер транзакций.
Важно — в mvc-config.xml прописана строчка <tx:annotation-driven/>. Без нее аннотация @Transactional работать не будет.
Полный application-context.xml с настройками из предыдущих частей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd "> <!--find property file. See bean id='dataSource' for example ${jdbc.hsqldb.driverClass}--> <context:property-placeholder location="classpath:util.properties" /> <!-- XML Bean Definitions --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.hsqldb.driverClass}" /> <property name="url" value="${jdbc.hsqldb.url}" /> <property name="username" value="${jdbc.hsqldb.username}" /> <property name="password" value="${jdbc.hsqldb.password}" /> </bean> <!-- initialize Embedded DataSource. Встроенная база данных--> <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:dbschema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:initialize-database> <!-- Java Mail Configuration --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="username" value="${java.mail.username}"/> <property name="password" value="${java.mail.password}"/> <property name="port" value="465"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.smtp.starttls.required">true</prop> <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> <prop key="mail.smtp.host">${java.mail.host}</prop> </props> </property> </bean> <!-- Velocity Email Template Config Bean --> <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> <property name="resourceLoaderPath" value="/WEB-INF/email-templates/"/> </bean> <!-- REST template configuration --> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/> <!--Do not forget activate @Transactional JPA annotation with <annotation-driven/>--> <!-- JPA Persistence Context and EntityManager configuration --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > <!--packagesToScan - search Entity and mapping them --> <property name="packagesToScan" value="ru.javastudy.mvcHtml5Angular.mvc.bean" /> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" > <property name="generateDdl" value="true" /> <property name="showSql" value="true" /> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!-- Automatic Transaction Participation--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!--not uses but could autowired in JDBCExample bean--> <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> --> </beans> |
4.1 mvc-config.xml
Кроме включения транзакций и добавления в начале пространства имен этот конфигурационный файл не изменился.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- context:component-scan This tag will scan @Component, @Repository, @Service, @Controller and also resolves @Autowired and @Qualifier --> <context:component-scan base-package="ru.javastudy.mvcHtml5Angular.mvc" /> <!-- mvc:annotation-driven configures Spring MVC annotations Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath. HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or @ExceptionHandler methods. --> <mvc:annotation-driven/> <!-- activate @Transactional JPA annotation --> <tx:annotation-driven/> <!-- ViewResolver bean config for mapping strings to jsp views --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' --> <property name="order" value="1" /> <property name="prefix" value="/WEB-INF/view/" /> <property name="suffix" value=".jsp" /> </bean> <!-- File Upload bean config--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- set the maximum file size in bytes --> <property name="maxUploadSize" value="1000000"/> </bean> <!--Excel and PDF xml view configuration --> <!--disabling for jUnit test. --> <bean class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="order" value="0" /> <property name="location" value="/WEB-INF/config/excel-pdf-config.xml"/> </bean> <mvc:view-controller path="/index.html" view-name="/index"/> <mvc:view-controller path="/about.html" view-name="/about/about"/> <mvc:view-controller path="/file.html" view-name="/file/file"/> <mvc:view-controller path="/jdbc.html" view-name="/jdbc/jdbc"/> <mvc:view-controller path="/email.html" view-name="/email/email"/> <mvc:view-controller path="/rest.html" view-name="/rest/rest"/> <mvc:view-controller path="/orm.html" view-name="/orm/orm"/> <!-- Static Resources Configuration (get access to static sources such as CSS and JavaScript files) --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- themes can be put in different folder such as <mvc:resources mapping="/resources/**" location="/resources/themeBlue" /> <mvc:resources mapping="/resources/**" location="/resources/themeGreen" /> --> </beans> |
5. web.xml
Здесь без изменений.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>mvc-html5-angularjs</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> WEB-INF/config/application-context.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/mvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--Позволяет работать с русскими символами--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/WEB-INF/view/index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/WEB-INF/view/error/errorpage.jsp</location> </error-page> </web-app> |
6. Java классы
Сначала опишу сервисный класс, который при вызове метода будет осуществлять запросы к базе данных.
Сервис класс ORMService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package ru.javastudy.mvcHtml5Angular.mvc.orm; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.TypedQuery; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import ru.javastudy.mvcHtml5Angular.mvc.bean.User; /** * Created for JavaStudy.ru on 28.02.2016. */ @Repository @Transactional //need to update\delete queries. Don't forget <tx:annotation-driven/> public class ORMService { @PersistenceContext private EntityManager entityManager; public List<User> queryFindAllUsersJPA() { System.out.println("ORMService queryfindAllUsersJPA is called"); String query = "from User order by iduser"; TypedQuery<User> typedQuery = entityManager.createQuery(query, User.class); return typedQuery.getResultList(); } public User queryFindUserById (int id) { System.out.println("ORMService queryFindUserById is called"); return entityManager.find(User.class, id); } public boolean updateUser(int id, boolean enabled) { System.out.println("ORMService updateUser is called"); String query= "update user set enabled = ? where iduser = ?"; Query nativeQuery = entityManager.createNativeQuery(query); nativeQuery.setParameter(1, enabled); nativeQuery.setParameter(2, id); int result = nativeQuery.executeUpdate(); return result > 0; // result show how many rows was updated. } public boolean insertUser(String username, String password, boolean enabled) { System.out.println("ORMExample insertUser is called"); String qlString = "insert into user (username,password,enabled) values (?,?,?)"; Query query = entityManager.createNativeQuery(qlString); query.setParameter(1, username); query.setParameter(2, password); query.setParameter(3, enabled); int result = query.executeUpdate(); return result > 0; } public boolean deleteUser(int idUser) { System.out.println("ORMExample deleteUser is called"); String qlString = "delete from user where iduser=?"; Query query = entityManager.createNativeQuery(qlString); query.setParameter(1, idUser); int result = query.executeUpdate(); return result > 0; } } |
Класс помечен двумя аннотациями, что делает его бином и позволяет поддерживать запросы обновления или удаления данных (а так же другие возможности). Затем вначале внедряется с помощью аннотации @PersistenceContext объект EntityManager. Это основной интерфейс для выполнения операций с базами данных в JPA. Далее описаны различные методы, названия которых поясняют их назначение.
Класс контроллер ORMController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package ru.javastudy.mvcHtml5Angular.mvc.orm; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import ru.javastudy.mvcHtml5Angular.mvc.bean.User; import java.util.List; /** * Created for JavaStudy.ru on 28.02.2016. */ @Controller public class ORMController { @Autowired private ORMService ormService; @RequestMapping(value = "/ormFindAllUsers", method= RequestMethod.GET) public ModelAndView ormFindAllUsers() { System.out.println("ORMController ormFindAllUsers is called"); List<User> users = ormService.queryFindAllUsersJPA(); return new ModelAndView("/orm/orm", "resultObject", users); } @RequestMapping(value = "/queryFindByIdUser/{userid}", method = RequestMethod.GET) public ModelAndView queryFindByIdUser(@PathVariable("userid") int userid) { System.out.println("ORMController queryFindByIdUser is called"); User user = ormService.queryFindUserById(userid); return new ModelAndView("/orm/orm", "resultObject", user); } @RequestMapping(value = "/ormUpdateUser/iduser/{iduser}/enabled/{enabled}", method=RequestMethod.GET) public ModelAndView ormUpdateUser( @PathVariable(value="iduser") int iduser, @PathVariable(value="enabled") boolean enabled) { System.out.println("ORMController ormUpdateUser is called"); boolean result = ormService.updateUser(iduser, enabled); return new ModelAndView("/orm/orm", "resultObject", result); } @RequestMapping(value = "/ormDeleteUser/iduser/{iduser}", method=RequestMethod.GET) public ModelAndView ormDeleteUser(@PathVariable(value="iduser") int iduser) { System.out.println("ORMController jdbcDelete is called"); boolean result = ormService.deleteUser(iduser); return new ModelAndView("/orm/orm", "resultObject", result); } @RequestMapping(value = "/ormInsertUser/username/{username}/password/{password}/enabled/{enabled}" , method=RequestMethod.GET) public ModelAndView ormInsertUser( @PathVariable(value="username") String username, @PathVariable(value="password") String password, @PathVariable(value="enabled") boolean enabled) { System.out.println("ORMController ormInsertUser is called"); boolean result = ormService.insertUser(username, password, enabled); return new ModelAndView("/orm/orm", "resultObject", result); } } |
Обычный контроллер Spring MVC, в котором в методы передаются параметры из запросов. Эти параметры обрабатываться с помощью аннотации @PathVariable, а в URI обозначаются в фигурных скобках, например {userid}. Далее с помощью внедренного объекта класса ORMService мы получаем информацию из базы данных.
Класс сущность User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package ru.javastudy.mvcHtml5Angular.mvc.bean; import org.hibernate.validator.constraints.NotEmpty; import javax.persistence.*; import javax.validation.constraints.Size; /** * Created for JavaStudy.ru on 25.02.2016. */ @Entity @Table(name = "USER") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "IDUSER") private int idUser; @NotEmpty @Size(min = 5, max = 20) @Column(name = "USERNAME") private String username; @NotEmpty @Size(min=5, max=20) @Column(name="PASSWORD") private String password; @Column(name="ENABLED") private boolean enabled; public int getIdUser() { return idUser; } public void setIdUser(int idUser) { this.idUser = idUser; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } @Override public String toString() { return "User{" + "idUser=" + idUser + ", username='" + username + '\'' + ", password='" + password + '\'' + ", enabled=" + enabled + '}'; } } |
Класс помечен аннотациями, которые делают из него сущность и связывают его с таблицей с определенным названием. Внутри сущности используются аннотации для предварительной валидации, указания связывания свойства класса с определенной колонкой и т.д. Подробнее можете прочитать в разделе Hibernate. Обратите внимание, что Spring сможет связать этот класс с таблицей, т.к. он будет найден из указания настройки в application-context.xml (<property name = «packagesToScan» value = «ru.javastudy.mvcHtml5Angular.mvc.bean» />).
7. Представление jsp
Оно ничем не отличается от предыдущих статей. Описаны колонки слева для выбора действия и отображения результата в правой части страницы. Для тех кто не читал первые статьи, то здесь используется шаблонизатор (шаблон находится в пакете WEB-INF/tags).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="page" tagdir="/WEB-INF/tags" %> <page:template> <jsp:body> <c:url value="/ormFindAllUsers" var="ormFindAllUsers" /> <c:url value="/queryFindByIdUser/4" var="queryFindByIdUser" /> <c:url value="/ormUpdateUser/iduser/3/enabled/false" var="ormUpdateUser" /> <c:url value="/ormDeleteUser/iduser/8" var="ormDeleteUser" /> <c:url value="/ormInsertUser/username/newUserHere/password/NewPass/enabled/true" var="ormInsertUser" /> <!-- Page Content --> <div class="container"> <!-- Page Heading/Breadcrumbs --> <div class="row"> <div class="col-lg-12"> <h1 class="page-header">Hibernate в Spring <small>Hibernate 5</small> </h1> <ol class="breadcrumb"> <li><a href="index.html">Home</a> </li> <li class="active">Hibernate page</li> </ol> </div> </div> <!-- /.row --> <!-- Content Row --> <div class="row"> <!-- Sidebar Column --> <div class="col-md-3"> <div class="list-group"> <a href="index.html" class="list-group-item">Home</a> <a href="${ormFindAllUsers}" class="list-group-item">Find All Users</a> <a href="${queryFindByIdUser}" class="list-group-item">Find User by id</a> <a href="${ormUpdateUser}" class="list-group-item">Update User</a> <a href="${ormDeleteUser}" class="list-group-item">Delete User</a> <a href="${ormInsertUser}" class="list-group-item">Insert User</a> </div> </div> <!-- Content Column --> <div class="col-md-9"> <c:if test="${not empty resultObject}"> Result: <c:if test="${resultObject == 'true'}"> <font color="green"><b>${resultObject}</b></font> </c:if> <c:if test="${resultObject == 'false'}"> <font color="red"><b>${resultObject}</b></font> </c:if> <c:if test="${resultObject !='true' and resultObject != 'false'}"> <p>${resultObject}</p> </c:if> </c:if> </div> </div> <!-- /.row --> <hr> </div> <!-- /.container --> </jsp:body> </page:template> |
8. База данных
Для этой статьи используются те же данные, что и для Spring MVC и JDBC (Spring JDBC example). Подключение и настройка JDBC datasource. Они будут доступны при скачивании исходных кодов для этой статьи внизу страницы. Напомню, что в dbschema.sql создаются таблицы (на старте приложения) и заполняются данными из test-data.sql.
9. Запуск и проверка работы приложения
Например, если нажать на Find All Users, то будет вызван метод ormFindAllUsers() из контроллера и возвращены все найденные пользователи.
Исходные коды
MVC_AngularJS_Html5 full project — полный проект Spring MVC + AngularJS + Bootstrap + HTML5.
6. Hibernate in Spring MVC — код для этой части
Обзор приложения Spring MVC + AngularJS + Bootstrap + HTML5
117 thoughts on “Spring MVC, JPA и Hibernate. Настройки JPA и ORM, создание сущностей, выполнение запросов к БД”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
Добрый день!
Может дать совет? По поводу Spring MVC
При запуске приложения возникает ошибка:
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘entityManagerFactory’ defined in ServletContext resource [/WEB-INF/config/application-context.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)V
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘entityManagerFactory’ defined in ServletContext resource [/WEB-INF/config/application-context.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)V
Помогите разобраться в чем дело.
Сам себе отвечу. Оказалось что в сервере jboss версия библиотеки jboss-logging была не та что нужно.
прочитал здесь: http://stackoverflow.com/questions/32912773/nosuchmethoderror-org-jboss-logging-logger-debugf
Спасибо, была таже проблема
Автор а как пользоваться не встроенной бд, а подключить базу данных из mysql workbanch?
указать datasource с подключением к бд типа MySql. На этом и многих других сайтах это есть.
А как возможно сделать так, чтоб выводилась не вся информация а только по заданному ИД. Т.е. на странице сделать поле ввода ИД, а как его использовать не могу понять.