鍍金池/ 教程/ Java/ Spring4 MVC + Hibernate4 + MySQL + Maven使用注解集成實(shí)例
Spring MVC表單處理
Spring MVC多項(xiàng)單選按鈕
Spring MVC Bean名稱Url處理程序映射
Spring MVC下拉選項(xiàng)(Select)
Spring MVC多動作控制器
Spring4 MVC RESTFul Web Services CRUD實(shí)例+RestTemplate
Spring MVC頁面重定向
Spring MVC資源綁定視圖解析器
Spring4 MVC+Hibernate4 Many-to-many連接表+MySQL+Maven實(shí)例
Spring4 MVC REST服務(wù)示例使用@RestController
Spring MVC文本域
Spring4 MVC + AngularJS使用$http異步服務(wù)交互
Spring4 MVC文件下載實(shí)例
Spring4 MVC表單驗(yàn)證
Spring4 MVC RESTFul WebServices CRUD實(shí)例+RestTemplate
Spring MVC教程
Spring MVC參數(shù)方法名稱解析器
Spring MVC生成JSON數(shù)據(jù)
Spring MVC生成XML
Spring4 MVC 表單驗(yàn)證和資源處理 (使用注解)
Spring MVC單選按鈕
Spring MVC Xml視圖解析器
Spring MVC復(fù)選框
Spring4 MVC ContentNegotiatingViewResolver多種輸出格式實(shí)例
Spring MVC錯(cuò)誤處理
Spring MVC復(fù)選框(多項(xiàng))
Spring MVC Hibernate驗(yàn)證器
Spring4 MVC Hello World注解 (Java Config)實(shí)例
Spring MVC靜態(tài)頁面
Spring4 MVC ContentNegotiatingViewResolver實(shí)例
Spring MVC列表多選框
Spring MVC生成Excel格式數(shù)據(jù)
Spring MVC文本框
Spring MVC內(nèi)部資源視圖解析器
Spring4 MVC HelloWorld 注解和JavaConfig實(shí)例
Spring4 MVC REST服務(wù)使用@RestController實(shí)例
Spring MVC簡單URL處理程序映射
Spring MVC4使用Servlet3 MultiPartConfigElement文件上傳實(shí)例
Spring MVC概述
Spring4 MVC使用Servlet 3 MultiPartConfigElement文件上傳實(shí)例
Spring4 MVC Hello WorldXML實(shí)例
Spring MVC屬性方法名稱解析器
Spring4 MVC + Hibernate4 + MySQL + Maven使用注解集成實(shí)例
Spring4 MVC + Hibernate4多對多連接表+MySQL+Maven實(shí)例
Spring4 MVC+Hibernate4+MySQL+Maven使用注解集成實(shí)例
Spring MVC配置靜態(tài)資源和資源包教程
Spring MVC可參數(shù)化的視圖控制器
Spring MVC生成RSS源
Spring4 MVC文件下載實(shí)例
Spring MVC密碼處理
Spring MVC隱藏字段域
Spring MVC文件上傳教程
Spring MVC多解析器映射
Spring MVC文件上傳處理
Spring4 MVC HelloWord實(shí)例
Spring MVC集成Log4j
Spring4 MVC+ AngularJS CRUD使用$http實(shí)例
Spring MVC - Hello World示例

Spring4 MVC + Hibernate4 + MySQL + Maven使用注解集成實(shí)例

在本教程中,我們將使用基于注解的配置集成Spring和Hibernate。 我們將開發(fā)包含表單要求用戶輸入一個(gè)簡單的CRUD為導(dǎo)向Web應(yīng)用程序,使用Hibernate保存輸入的數(shù)據(jù)到 MySQL 數(shù)據(jù)庫,從數(shù)據(jù)庫和更新檢索記錄或刪除它們在事務(wù)中,全部采用注解配置。
使用以下技術(shù):
  • Spring 4.0.6.RELEASE
  • Hibernate Core 4.3.6.Final
  • validation-api 1.1.0.Final
  • hibernate-validator 5.1.3.Final
  • MySQL Server 5.6
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2
  • TestNG 6.9.4
  • Mockito 1.10.19
  • DBUnit 2.2
  • H2 Database 1.4.187

現(xiàn)在,讓我們開始

第1步:創(chuàng)建目錄結(jié)構(gòu)

以下是最終的項(xiàng)目結(jié)構(gòu):

現(xiàn)在讓我們來添加上每個(gè)細(xì)節(jié)上述結(jié)構(gòu)中提到的內(nèi)容。

第2步:更新 pom.xml,包括所需的依賴關(guān)系

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yiibai.springmvc</groupId>
	<artifactId>SpringHibernateExample</artifactId>
	<packaging>war</packaging>
	<version>1.0.0</version>
	<name>SpringHibernateExample</name>

	<properties>
		<springframework.version>4.0.6.RELEASE</springframework.version>
		<hibernate.version>4.3.6.Final</hibernate.version>
		<mysql.connector.version>5.1.31</mysql.connector.version>
		<joda-time.version>2.3</joda-time.version>
		<testng.version>6.9.4</testng.version>
		<mockito.version>1.10.19</mockito.version>
		<h2.version>1.4.187</h2.version>
		<dbunit.version>2.2</dbunit.version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<!-- jsr303 validation -->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.1.3.Final</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.connector.version}</version>
		</dependency>

      	<!-- Joda-Time -->		
		<dependency>
  			<groupId>joda-time</groupId>
  			<artifactId>joda-time</artifactId>
  			<version>${joda-time.version}</version>
  		</dependency>
		
		<!-- To map JodaTime with database type -->  		
  		<dependency>
    		<groupId>org.jadira.usertype</groupId>
    		<artifactId>usertype.core</artifactId>
    		<version>3.0.0.CR1</version>
		</dependency>

		<!-- Servlet+JSP+JSTL -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
		
		
		<!-- Testing dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${springframework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>${testng.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>${mockito.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>${h2.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>dbunit</groupId>
			<artifactId>dbunit</artifactId>
			<version>${dbunit.version}</version>
			<scope>test</scope>
		</dependency>
		
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.4</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<warName>SpringHibernateExample</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
		<finalName>SpringHibernateExample</finalName>
	</build>
</project>

首先要注意這里是 maven-war-plugin 插件聲明。由于我們使用的是全注解的配置,所以不包函 web.xml 文件在項(xiàng)目中,所以我們需要配置這個(gè)插件以避免 Maven 構(gòu)建 war 包失敗。因?yàn)樵谶@個(gè)例子中,我們將用一個(gè)表單來接受來自用戶的輸入,我們也需要驗(yàn)證用戶的輸入。在這里我們將選擇JSR303驗(yàn)證,所以我們包括驗(yàn)證,API 代表了規(guī)范,hibernate-validator它代表本規(guī)范的實(shí)現(xiàn)。hibernate-validator 還提供了一些它自己的注解(@Email,@NotEmpty等)不屬于規(guī)范的一部分。

伴隨著這一點(diǎn),我們也包括 JSP/Servlet/Jstl 依賴關(guān)系,也將需要為使用的 servlet API和JSTL視圖在代碼中。在一般情況下,容器可能已經(jīng)包含了這些庫,從而在 pom.xml 中“提供”了我們可以設(shè)置的范圍。

步驟3:配置Hibernate

com.yiibai.springmvc.configuration.HibernateConfiguration

package com.yiibai.springmvc.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.yiibai.springmvc.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {

    @Autowired
    private Environment environment;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.yiibai.springmvc.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }
	
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }
    
    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;        
    }
    
	@Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    }
} 

@Configuration表示該類包含注解為 @Bean生產(chǎn)Bean管理是由Spring容器的一個(gè)或多個(gè)bean的方法。在我們的例子中,這個(gè)類代表hibernate配置。

@ComponentScan 相當(dāng)于 context:component-scan base-package="..." 在xml文件中配置, 提供Spring在哪里尋找管理 beans/classes。

@EnableTransactionManagement 相當(dāng)于 Spring’s tx:* XML 命名空間, 使Spring注解驅(qū)動事務(wù)管理能力。

@PropertySource 用于聲明一組屬性(在屬性中定義的應(yīng)用程序類路徑文件)在Spring運(yùn)行時(shí) Environment提供了靈活性,可以在不同的應(yīng)用環(huán)境的不同值。

下面是這篇文章中使用的屬性文件。

/src/main/resources/application.properties

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/yiibai
jdbc.username = root
jdbc.password = passwd123
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true

第4步:配置Spring MVC

com.yiibai.springmvc.configuration.AppConfig

package com.yiibai.springmvc.configuration;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.yiibai.springmvc")
public class AppConfig {
	
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
	
	@Bean
	public MessageSource messageSource() {
	    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	    messageSource.setBasename("messages");
	    return messageSource;
	}
}
同樣,@Configuration標(biāo)志著這一類配置類如上所述與器件掃描是指包位置找到相關(guān)的Bean類。
@EnableWebMvc相當(dāng)于mvc:annotation-driven 在XML文件中。
ViewResolver方法配置一個(gè)ViewResolver來找出真正的視圖。

在這篇文章中,我們提交表單并驗(yàn)證用戶輸入(通過JSR303注解)。在校驗(yàn)失敗后,默認(rèn)的錯(cuò)誤消息會顯示。要通過自己的自定義覆蓋默認(rèn)的[國際化]從外部消息包的消息[.properties文件],我們需要配置一個(gè)ResourceBundleMessageSource。messageSource方法有同樣的目的。請注意,以basename方法提供的參數(shù)(消息)。Spring將搜索應(yīng)用程序類路徑中一個(gè)名為 messages.properties 的文件。讓我們添加的文件:

/src/main/resources/messages.properties

Size.employee.name=Name must be between {2} and {1} characters long
NotNull.employee.joiningDate=Joining Date can not be blank
NotNull.employee.salary=Salary can not be blank
Digits.employee.salary=Only numeric data with max 8 digits and with max 2 precision is allowed
NotEmpty.employee.ssn=SSN can not be blank
typeMismatch=Invalid format
non.unique.ssn=SSN {0} already exist. Please fill in different value.
請注意,上述消息按照特定的模式:
{ValidationAnnotationClass}.{modelObject}.{fieldName} 

此外,根據(jù)具體注解(如@Size),你也可以用傳遞參數(shù)給這些消息{0},{1},..{i}索引。

步驟5:配置初始化器類

com.yiibai.springmvc.configuration.AppInitializer

package com.yiibai.springmvc.configuration;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class AppInitializer implements WebApplicationInitializer {

	public void onStartup(ServletContext container) throws ServletException {

		AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
		ctx.register(AppConfig.class);
		ctx.setServletContext(container);

		ServletRegistration.Dynamic servlet = container.addServlet(
				"dispatcher", new DispatcherServlet(ctx));

		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
	}

} 

上面的內(nèi)容類似于web.xml,因?yàn)槲覀兪褂玫氖乔岸丝刂破?nbsp;DispatcherServlet 的內(nèi)容,分配映射(URL模式的XML),而不是提供給Spring配置文件(spring-servlet.xml)的路徑,在這里我們正在注冊的配置類。

更新:請注意,上面的類可以寫成更加簡潔[最佳方法],通過擴(kuò)展 AbstractAnnotationConfigDispatcherServletInitializer 基類,如下所示:

package com.yiibai.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
 
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

}

第6步:添加控制器來處理請求

添加控制器這將有助于處理 GET和POST請求。

com.yiibai.springmvc.controller.AppController

package com.yiibai.springmvc.controller;

import java.util.List;
import java.util.Locale;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.yiibai.springmvc.model.Employee;
import com.yiibai.springmvc.service.EmployeeService;

@Controller
@RequestMapping("/")
public class AppController {

	@Autowired
	EmployeeService service;
	
	@Autowired
	MessageSource messageSource;

	/*
	 * This method will list all existing employees.
	 */
	@RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)
	public String listEmployees(ModelMap model) {

		List<Employee> employees = service.findAllEmployees();
		model.addAttribute("employees", employees);
		return "allemployees";
	}

	/*
	 * This method will provide the medium to add a new employee.
	 */
	@RequestMapping(value = { "/new" }, method = RequestMethod.GET)
	public String newEmployee(ModelMap model) {
		Employee employee = new Employee();
		model.addAttribute("employee", employee);
		model.addAttribute("edit", false);
		return "registration";
	}

	/*
	 * This method will be called on form submission, handling POST request for
	 * saving employee in database. It also validates the user input
	 */
	@RequestMapping(value = { "/new" }, method = RequestMethod.POST)
	public String saveEmployee(@Valid Employee employee, BindingResult result,
			ModelMap model) {

		if (result.hasErrors()) {
			return "registration";
		}

		/*
		 * Preferred way to achieve uniqueness of field [ssn] should be implementing custom @Unique annotation 
		 * and applying it on field [ssn] of Model class [Employee].
		 * 
		 * Below mentioned peace of code [if block] is to demonstrate that you can fill custom errors outside the validation
		 * framework as well while still using internationalized messages.
		 * 
		 */
		if(!service.isEmployeeSsnUnique(employee.getId(), employee.getSsn())){
			FieldError ssnError =new FieldError("employee","ssn",messageSource.getMessage("non.unique.ssn", new String[]{employee.getSsn()}, Locale.getDefault()));
		    result.addError(ssnError);
			return "registration";
		}
		
		service.saveEmployee(employee);

		model.addAttribute("success", "Employee " + employee.getName() + " registered successfully");
		return "success";
	}


	/*
	 * This method will provide the medium to update an existing employee.
	 */
	@RequestMapping(value = { "/edit-{ssn}-employee" }, method = RequestMethod.GET)
	public String editEmployee(@PathVariable String ssn, ModelMap model) {
		Employee employee = service.findEmployeeBySsn(ssn);
		model.addAttribute("employee", employee);
		model.addAttribute("edit", true);
		return "registration";
	}
	
	/*
	 * This method will be called on form submission, handling POST request for
	 * updating employee in database. It also validates the user input
	 */
	@RequestMapping(value = { "/edit-{ssn}-employee" }, method = RequestMethod.POST)
	public String updateEmployee(@Valid Employee employee, BindingResult result,
			ModelMap model, @PathVariable String ssn) {

		if (result.hasErrors()) {
			return "registration";
		}

		if(!service.isEmployeeSsnUnique(employee.getId(), employee.getSsn())){
			FieldError ssnError =new FieldError("employee","ssn",messageSource.getMessage("non.unique.ssn", new String[]{employee.getSsn()}, Locale.getDefault()));
		    result.addError(ssnError);
			return "registration";
		}

		service.updateEmployee(employee);

		model.addAttribute("success", "Employee " + employee.getName()	+ " updated successfully");
		return "success";
	}

	
	/*
	 * This method will delete an employee by it's SSN value.
	 */
	@RequestMapping(value = { "/delete-{ssn}-employee" }, method = RequestMethod.GET)
	public String deleteEmployee(@PathVariable String ssn) {
		service.deleteEmployeeBySsn(ssn);
		return "redirect:/list";
	}

} 

這是一個(gè)非常直接的基于Spring的控制器。 @Controller表明這個(gè)類是一個(gè)控制器在處理與模式映射@RequestMapping請求。這里用“/”,它被作為默認(rèn)的控制器。

listEmployees方法標(biāo)注了@ RequestMethod.GET,同時(shí)處理默認(rèn)的網(wǎng)址 “/” 和 ‘/list’。它充當(dāng)處理應(yīng)用初始頁面,顯示現(xiàn)有雇員的列表。

newEmployee方法處理新員工注冊頁面的GET請求, 表示通過模型 Employee 對象支持頁面。

方法 saveEmployee 被注解為@ RequestMethod.POST,并且將處理新員工登記表單提交 POST 請求 (‘/new’)。注間這個(gè)方法的參數(shù)和它們的順序。

@Valid要求Spring來驗(yàn)證相關(guān)的對象(Employee)。 BindingResult包含此驗(yàn)證,并可能在此驗(yàn)證過程中發(fā)生任何錯(cuò)誤的結(jié)果。請注意,BindingResult必須出現(xiàn)在驗(yàn)證對象,否則Spring將無法驗(yàn)證并且拋出一個(gè)異常。 如果驗(yàn)證失敗,自定義錯(cuò)誤信息(因?yàn)槲覀円呀?jīng)配置在步驟4)中顯示。

我們還包括代碼檢查SSN唯一性,因?yàn)樗暶饕跀?shù)據(jù)庫中具有唯一必。保存/更新員工之前要檢查,如果SSN是否獨(dú)一無二。如果沒有,我們生成驗(yàn)證錯(cuò)誤和重定向到注冊頁面。 這個(gè)代碼展示出一種方式來填充在自定義錯(cuò)誤校驗(yàn)框架之外,同時(shí)仍使用國際化的信息。

第7步:添加DAO層

com.yiibai.springmvc.dao.AbstractDao

package com.yiibai.springmvc.dao;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class AbstractDao<PK extends Serializable, T> {
	
	private final Class<T> persistentClass;
	
	@SuppressWarnings("unchecked")
	public AbstractDao(){
		this.persistentClass =(Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
	}
	
	@Autowired
	private SessionFactory sessionFactory;

	protected Session getSession(){
		return sessionFactory.getCurrentSession();
	}

	@SuppressWarnings("unchecked")
	public T getByKey(PK key) {
		return (T) getSession().get(persistentClass, key);
	}

	public void persist(T entity) {
		getSession().persist(entity);
	}

	public void delete(T entity) {
		getSession().delete(entity);
	}
	
	protected Criteria createEntityCriteria(){
		return getSession().createCriteria(persistentClass);
	}

} 

這個(gè)通用類是所有的DAO實(shí)現(xiàn)類的基類。它提供包裝方法也是常見的hibernate 操作。

注意上面,我們已經(jīng)在前面第3步創(chuàng)建了SessionFactory,在這里將自動裝配。

com.yiibai.springmvc.dao.EmployeeDao

package com.yiibai.springmvc.dao;

import java.util.List;

import com.yiibai.springmvc.model.Employee;

public interface EmployeeDao {

	Employee findById(int id);

	void saveEmployee(Employee employee);
	
	void deleteEmployeeBySsn(String ssn);
	
	List<Employee> findAllEmployees();

	Employee findEmployeeBySsn(String ssn);

}

com.yiibai.springmvc.dao.EmployeeDaoImpl

package com.yiibai.springmvc.dao;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.yiibai.springmvc.model.Employee;

@Repository("employeeDao")
public class EmployeeDaoImpl extends AbstractDao<Integer, Employee> implements EmployeeDao {

	public Employee findById(int id) {
		return getByKey(id);
	}

	public void saveEmployee(Employee employee) {
		persist(employee);
	}

	public void deleteEmployeeBySsn(String ssn) {
		Query query = getSession().createSQLQuery("delete from Employee where ssn = :ssn");
		query.setString("ssn", ssn);
		query.executeUpdate();
	}

	@SuppressWarnings("unchecked")
	public List<Employee> findAllEmployees() {
		Criteria criteria = createEntityCriteria();
		return (List<Employee>) criteria.list();
	}

	public Employee findEmployeeBySsn(String ssn) {
		Criteria criteria = createEntityCriteria();
		criteria.add(Restrictions.eq("ssn", ssn));
		return (Employee) criteria.uniqueResult();
	}
}

第8步:添加服務(wù)層

com.yiibai.springmvc.service.EmployeeService

package com.yiibai.springmvc.service;

import java.util.List;

import com.yiibai.springmvc.model.Employee;

public interface EmployeeService {

	Employee findById(int id);
	
	void saveEmployee(Employee employee);
	
	void updateEmployee(Employee employee);
	
	void deleteEmployeeBySsn(String ssn);

	List<Employee> findAllEmployees(); 
	
	Employee findEmployeeBySsn(String ssn);

	boolean isEmployeeSsnUnique(Integer id, String ssn);
	
}

com.yiibai.springmvc.service.EmployeeServiceImpl

package com.yiibai.springmvc.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yiibai.springmvc.dao.EmployeeDao;
import com.yiibai.springmvc.model.Employee;

@Service("employeeService")
@Transactional
public class EmployeeServiceImpl implements EmployeeService {

	@Autowired
	private EmployeeDao dao;
	
	public Employee findById(int id) {
		return dao.findById(id);
	}

	public void saveEmployee(Employee employee) {
		dao.saveEmployee(employee);
	}

	/*
	 * Since the method is running with Transaction, No need to call hibernate update explicitly.
	 * Just fetch the entity from db and update it with proper values within transaction.
	 * It will be updated in db once transaction ends. 
	 */
	public void updateEmployee(Employee employee) {
		Employee entity = dao.findById(employee.getId());
		if(entity!=null){
			entity.setName(employee.g