Spring4 MVC+Hibernate4+MySQL+Maven使用註解集成實例
在本教程中,我們將使用基於註解的配置集成Spring和Hibernate。 我們將開發包含表單要求用戶輸入一個簡單的CRUD爲導向Web應用程序,使用Hibernate保存輸入的數據到 MySQL 數據庫,從數據庫和更新檢索記錄或刪除它們在事務中,全部採用註解配置。
使用以下技術:
- 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
現在,讓我們開始
第1步:創建目錄結構
以下是最終的項目結構:
現在讓我們來添加上每個細節上述結構中提到的內容。
第2步:更新 pom.xml,包括所需的依賴關係
<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>
首先要注意這裏是 maven-war-plugin 插件聲明。由於我們使用的是全註解的配置,所以不包函 web.xml 文件在項目中,所以我們需要配置這個插件以避免 Maven 構建 war 包失敗。因爲在這個例子中,我們將用一個表單來接受來自用戶的輸入,我們也需要驗證用戶的輸入。在這裏我們將選擇JSR303驗證,所以我們包括驗證,API 代表了規範,hibernate-validator它代表本規範的實現。hibernate-validator 還提供了一些它自己的註解(@Email,@NotEmpty等)不屬於規範的一部分。
伴隨着這一點,我們也包括 JSP/Servlet/Jstl 依賴關係,也將需要爲使用的 servlet API和JSTL視圖在代碼中。在一般情況下,容器可能已經包含了這些庫,從而在 pom.xml 中「提供」了我們可以設置的範圍。
步驟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生產Bean管理是由Spring容器的一個或多個bean的方法。在我們的例子中,這個類代表hibernate配置。
@ComponentScan 相當於 context:component-scan base-package="..." 在xml文件中配置, 提供Spring在哪裏尋找管理 beans/classes。
@EnableTransactionManagement 相當於 Spring’s tx:* XML 命名空間, 使Spring註解驅動事務管理能力。
@PropertySource 用於聲明一組屬性(在屬性中定義的應用程序類路徑文件)在Spring運行時 Environment, 提供了靈活性,可以在不同的應用環境的不同值。
下面是這篇文章中使用的屬性文件。
/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標誌着這一類配置類如上所述與器件掃描是指包位置找到相關的Bean類。
@EnableWebMvc相當於mvc:annotation-driven 在XML文件中。
ViewResolver方法配置一個ViewResolver來找出真正的視圖。
在這篇文章中,我們提交表單並驗證用戶輸入(通過JSR303註解)。在校驗失敗後,默認的錯誤消息會顯示。要通過自己的自定義覆蓋默認的[國際化]從外部消息包的消息[.properties文件],我們需要配置一個ResourceBundleMessageSource。messageSource方法有同樣的目的。請注意,以basename方法提供的參數(消息)。Spring將搜索應用程序類路徑中一個名爲 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}
此外,根據具體註解(如@Size),你也可以用傳遞參數給這些消息{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("/");
}
}
上面的內容類似於web.xml,因爲我們使用的是前端控制器 DispatcherServlet 的內容,分配映射(URL模式的XML),而不是提供給Spring配置文件(spring-servlet.xml)的路徑,在這裏我們正在註冊的配置類。
更新:請注意,上面的類可以寫成更加簡潔[最佳方法],通過擴展 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";
}
}
這是一個非常直接的基於Spring的控制器。 @Controller表明這個類是一個控制器在處理與模式映射@RequestMapping請求。這裏用「/」,它被作爲默認的控制器。
listEmployees方法標註了@ RequestMethod.GET,同時處理默認的網址 「/」 和 ‘/list’。它充當處理應用初始頁面,顯示現有僱員的列表。
newEmployee方法處理新員工註冊頁面的GET請求, 表示通過模型 Employee 對象支持頁面。
方法 saveEmployee 被註解爲@ RequestMethod.POST,並且將處理新員工登記表單提交 POST 請求 (‘/new’)。注間這個方法的參數和它們的順序。
@Valid要求Spring來驗證相關的對象(Employee)。 BindingResult包含此驗證,並可能在此驗證過程中發生任何錯誤的結果。請注意,BindingResult必須出現在驗證對象,否則Spring將無法驗證並且拋出一個異常。 如果驗證失敗,自定義錯誤信息(因爲我們已經配置在步驟4)中顯示。
我們還包括代碼檢查SSN唯一性,因爲它聲明要在數據庫中具有唯一必。保存/更新員工之前要檢查,如果SSN是否獨一無二。如果沒有,我們生成驗證錯誤和重定向到註冊頁面。 這個代碼展示出一種方式來填充在自定義錯誤校驗框架之外,同時仍使用國際化的信息。
第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);
}
}
這個通用類是所有的DAO實現類的基類。它提供包裝方法也是常見的hibernate 操作。
注意上面,我們已經在前面第3步創建了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步:添加服務層
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.getName());
entity.setJoiningDate(employee.getJoiningDate());
entity.setSalary(employee.getSalary());
entity.setSsn(employee.getSsn());
}
}
public void deleteEmployeeBySsn(String ssn) {
dao.deleteEmployeeBySsn(ssn);
}
public List<Employee> findAllEmployees() {
return dao.findAllEmployees();
}
public Employee findEmployeeBySsn(String ssn) {
return dao.findEmployeeBySsn(ssn);
}
public boolean isEmployeeSsnUnique(Integer id, String ssn) {
Employee employee = findEmployeeBySsn(ssn);
return ( employee == null || ((id != null) && (employee.getId() == id)));
}
}
上面最有趣的部分是 @Transactional 它開始在每個方法啓動一個事務,並提交其上的每個方法退出(或回滾,如果方法失敗,會發生是一個錯誤)。 注意,因爲該事務是在方法範圍,和內部的方法,我們將使用DAO,DAO方法將在同一事務內執行。
第9步:創建域實體類(POJO)
讓我們創建實際的員工實體數據表。
com.yiibai.springmvc.model.Employee
package com.yiibai.springmvc.model;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.NotEmpty;
import org.joda.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Size(min=3, max=50)
@Column(name = "NAME", nullable = false)
private String name;
@NotNull
@DateTimeFormat(pattern="dd/MM/yyyy")
@Column(name = "JOINING\_DATE", nullable = false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate joiningDate;
@NotNull
@Digits(integer=8, fraction=2)
@Column(name = "SALARY", nullable = false)
private BigDecimal salary;
@NotEmpty
@Column(name = "SSN", unique=true, nullable = false)
private String ssn;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getJoiningDate() {
return joiningDate;
}
public void setJoiningDate(LocalDate joiningDate) {
this.joiningDate = joiningDate;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime \* result + id;
result = prime \* result + ((ssn == null) ? 0 : ssn.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Employee))
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (ssn == null) {
if (other.ssn != null)
return false;
} else if (!ssn.equals(other.ssn))
return false;
return true;
}
@Override
public String toString() {
return "Employee \[id=" + id + ", name=" + name + ", joiningDate="
+ joiningDate + ", salary=" + salary + ", ssn=" + ssn + "\]";
}
}
這是註明使用JPA註解@Entity,@Table,@Column 使用 hibernate的具體註釋@Type,我們正在使用提供數據庫中的數據類型和LocalDate之間的映射標準的實體類。
@DateTimeFormat是一個 Spring 的具體註解聲明,字段應該使用一個給定格式格式化日期時間。
第10步:添加視圖/JSP
WEB-INF/views/allemployees.jsp [主頁包含所有現有員工列表]
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="uft-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<style>
tr:first-child{
font-weight: bold;
background-color: #C6C9C4;
}
</style>
List of Employees
NAME | Joining Date | Salary | SSN | |
${employee.name} | ${employee.joiningDate} | ${employee.salary} | ${employee.ssn} | delete |
Add New Employee
WEB-INF/views/registration.jsp [註冊頁面用來創建和保存在數據庫中的新員工]
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h2>Registration Form</h2>
<form:form method="POST" modelAttribute="employee">
<form:input type="hidden" path="id" id="id"/>
<table>
<tr>
<td><label for="name">Name: </label> </td>
<td><form:input path="name" id="name"/></td>
<td><form:errors path="name" cssClass="error"/></td>
</tr>
<tr>
<td><label for="joiningDate">Joining Date: </label> </td>
<td><form:input path="joiningDate" id="joiningDate"/></td>
<td><form:errors path="joiningDate" cssClass="error"/></td>
</tr>
<tr>
<td><label for="salary">Salary: </label> </td>
<td><form:input path="salary" id="salary"/></td>
<td><form:errors path="salary" cssClass="error"/></td>
</tr>
<tr>
<td><label for="ssn">SSN: </label> </td>
<td><form:input path="ssn" id="ssn"/></td>
<td><form:errors path="ssn" cssClass="error"/></td>
</tr>
<tr>
<td colspan="3">
<c:choose>
<c:when test="${edit}">
<input type="submit" value="Update"/>
</c:when>
<c:otherwise>
<input type="submit" value="Register"/>
</c:otherwise>
</c:choose>
</td>
</tr>
</table>
</form:form>
<br/>
<br/>
Go back to <a href="<c:url value='/list' />">List of All Employees</a>
WEB-INF/views/success.jsp [包括成功頁面新員工創建一個確認,並鏈接回員工列表]
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Go back to List of All Employees
第11步:在數據庫創建模式
CREATE TABLE EMPLOYEE(
id INT NOT NULL auto_increment,
name VARCHAR(50) NOT NULL,
joining_date DATE NOT NULL,
salary DOUBLE NOT NULL,
ssn VARCHAR(30) NOT NULL UNIQUE,
PRIMARY KEY (id)
);
第12步:構建,部署和運行應用程序
現在構建(參考提到的前面Eclipse教程)或通過Maven的命令行( mvn clean install). 部署War到Servlet3.0容器。
打開瀏覽器,瀏覽: http://localhost:8080/SpringHibernateExample/
現在,點擊「Add New Employee」,並點擊註冊按鈕但不填寫任何信息:
現在填寫詳細信息
點擊註冊(Register),應該得到類似的東西:
點擊列表,進入列表:
現在添加幾個記錄和以前一樣:
現在點擊第二記錄的刪除鏈接,它應該被刪除了,如下圖:
現在點擊SSN鏈接(這是一個更新),第二要記錄要更新:
現在,編輯一些字段,此外SSN值更改爲現有的記錄中的值:
嘗試更新,你應該得到驗證錯誤的SSN:
修正了錯誤,通過改變SSN以唯一值更新,然後查看記錄的完整列表,看到更新有了變化(這裏修改SSN爲:123456):
最後,查看數據庫在這時是:
到這裏,整個教程完成,包教不包會!