spring mvc 与JPA/Hibernate的整合示例
一、首先通过maven加入spring、jpa和hibernate相关的jar包。如pom.xml:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId> cn.ibeans</groupId> <artifactId>ibeans</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>myweb Maven Webapp</name> <url>http://maven.apache.org</url> <!-- 定义相关属性 --> <properties> <jdk-version>1.6</jdk-version> <junit-version>4.11</junit-version> <spring-version>3.2.2.RELEASE</spring-version> </properties> <!-- 定义依赖包 --> <dependencies> <!-- spring begin--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency><dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.3.2.RELEASE</version> </dependency><!-- spring end --><!-- servlet begin --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1</version> <scope>provided</scope> </dependency><!-- servlet end --><!-- junit begin --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit-version}</version> <scope>test</scope> </dependency><!-- junit end --><!-- hibernate begin --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.2.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.2.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.common</groupId> <artifactId>hibernate-commons-annotations</artifactId> <version>4.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.0.0.Final</version> </dependency> <!-- hibernate end --> <!--logger begin --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> <!-- logger end --> <!-- database begin --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency><!-- database end --><!-- apache commons begin --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>20030825.184428</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>20030825.183949</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>2.1</version> </dependency><!-- apache commons end --> </dependencies> <!-- 配置构建 --> <build> <finalName>ibeans</finalName> </build></project>2、配置applicationContext.xml中的实体管理工厂和事务机制:
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"default-lazy-init="true"><description>Spring公共配置 </description><!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 --><context:component-scan base-package="cn.ibeans"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan><!-- JPA实体管理工厂的配置 --><bean id="entityManagerFactory" ref="dataSource"/><property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/><property name="packagesToScan" value="cn.ibeans"/><!--待扫描的实体类包,不再需要persistence.xml了--><property name="jpaProperties"><props><prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.hbm2ddl.auto">update</prop></props></property></bean><!--指定实现JPA的适配器--><bean id="hibernateJpaVendorAdapter" value="org.hibernate.dialect.MySQLDialect" /></bean><!-- Jpa 事务配置 --><bean id="transactionManager" ref="entityManagerFactory"/></bean><!-- Spring Data Jpa配置 --><!--<jpa:repositories base-package="cn.ibeans" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>--><!-- 使用annotation定义事务 --><tx:annotation-driven transaction-manager="transactionManager" proxy-target-/><!-- JSR303 Validator定义 --> <bean id="validator" /><!-- production环境 --> <beans profile="production"> <context:property-placeholder ignore-unresolvable="true" location="classpath*:/db.properties" /><!-- 数据源配置, 使用DBCP数据库连接池 --><bean id="dataSource" destroy-method="close"><!-- Connection Info --><property name="driverClassName" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><!-- Connection Pooling Info --><property name="maxActive" value="${dbcp.maxActive}" /><property name="maxIdle" value="${dbcp.maxIdle}" /><property name="defaultAutoCommit" value="false" /><!-- 连接Idle一个小时后超时 --><property name="timeBetweenEvictionRunsMillis" value="3600000" /><property name="minEvictableIdleTimeMillis" value="3600000" /></bean><!-- 数据源配置,使用应用服务器的数据库连接池 --><!--<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/ExampleDB" />--></beans><!-- local development环境 --><beans profile="development"><context:property-placeholder ignore-resource-not-found="true"location="classpath*:/db.properties, classpath*:/db_dev.properties" /><!-- DBCP连接池 --><bean id="dataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="defaultAutoCommit" value="false" /></bean></beans><!-- unit test环境 --><beans profile="test"> <context:property-placeholder ignore-resource-not-found="true"location="classpath*:/db_test.properties" /><!-- Simple连接池 --><bean id="dataSource" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!-- 初始化数据表结构 与默认数据--><jdbc:initialize-database data-source="dataSource" ignore-failures="ALL"><jdbc:script location="classpath:sql/h2/schema.sql" /><jdbc:script location="classpath:data/import-data.sql" encoding="UTF-8"/></jdbc:initialize-database></beans></beans>定义实体类:User.java
package cn.ibeans.web.model;import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;import org.hibernate.annotations.GenericGenerator;@Entity@Table(name="i_user")public class User implements Serializable{private String id;private String username;private String password;@Id@GeneratedValue(generator="system-uuid")@GenericGenerator(name="system-uuid",strategy="uuid")public String getId() {return id;}public void setId(String id) {this.id = id;}@Column(name="username")public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Column(name="password")public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}3、定义dao接口,只需定义接口方法即可,不用加任何注解
package cn.ibeans.dao;import cn.ibeans.web.model.User;public interface UserDao {User findByName(String name);User findByLoginName(String loginName);void saveOrUpdate(User user);}4、定义dao实现类。用@Repository注解类,并将EntityManager作为成员变量注入,注入方法是加@PersistenceContext
package cn.ibeans.dao.impl;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import org.springframework.stereotype.Repository;import cn.ibeans.dao.UserDao;import cn.ibeans.web.model.User;@Repositorypublic class UserDaoImpl implements UserDao {@PersistenceContextprivate EntityManager em;@Overridepublic User findByName(String name) {return null;}@Overridepublic User findByLoginName(String loginName) {return null;}@Overridepublic void saveOrUpdate(User user) {em.persist(user);}}5、定义service类。可直接写实现类
用@Component或@Service注释类,将dao接口作为成员变量注入,注入方法是加@Autowired
如果是写方法,需在方法上加@Transactional(readOnly=false)注解
package cn.ibeans.service;import javax.annotation.Resource;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;import cn.ibeans.dao.UserDao;import cn.ibeans.web.model.User;@Componentpublic class UserService {private static Logger logger = Logger.getLogger(UserService.class);@Autowiredprivate UserDao userDao;@Transactional(readOnly=false)public void saveUser(User user){userDao.saveOrUpdate(user);logger.debug(user.getUsername()+",保存成功!");}}6、定义action
用@Controller注释action类,如果需为该action中所有方法指定一个共用的上层路径名,则需用@RequestMapping(value="/user")注释该类。表示该类下的所有访求均要通过/user/**来访问
将service类作为成员变量注入action。注入方法是加@Autowired
用@RequestMapping(value="/save")注释action的方法。
package cn.ibeans.web.controller;import javax.servlet.ServletContext;import javax.servlet.http.HttpServlet;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.context.ContextLoader;import org.springframework.web.context.WebApplicationContext;import cn.ibeans.service.UserService;import cn.ibeans.web.model.User;@Controller@RequestMapping(value="/user")public class LoginController extends HttpServlet{private static Logger log = Logger.getLogger(LoginController.class);@Autowiredprivate UserService userService;//@RequestMapping(value="/login")//如果类级别上已有映射地址(/user),此处的完整请求地址是/user/loginpublic String doLogin(Model model,Object loginForm){//model.addAttribute("username",username);//model被用来封装数据,向前台传递WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();ServletContext sc = context.getServletContext();return "/welcome";}@RequestMapping(value="/login")public String login(@ModelAttribute User user,Model model){log.info(user.getUsername());model.addAttribute(user);return "/welcome";}@RequestMapping(value="/save")public String save(@ModelAttribute User user,Model model){log.info(user.getUsername());userService.saveUser(user);model.addAttribute(user);return "/welcome";}}7、发起请示的页面
请示的url应该是上下文根路径+action类路径+方法路径
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <div> <form action="/ibeans/user/save" methed="post"> <input type="text" name="username"> <input type="text" name="password"> <input type="submit" value="SUBMIT"> </form> </div> </body> </html>
8、转发目的页面
可以通过引用action方法里定义的mode属性来获取相关的数据。
welcome.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> ${user.username },你好! </body> </html>