Spring has an awesome feature to deal with Hibernate. For a traditional Hibernate application, you need a hibernate configuration file, a number of mapping files for tables. But Spring reduces that overhead and introduces a new Annotation based mapping. At last, we dont need to brag with that XML files and much cleaner when it looks in POJO.
Thanks Patrick Grimard for giving such wonderful article. I just altered his code according to my need and the tutorial was written by him.
Lets have a look at this. First we need to map the DispatcherServlet in the web.xml file.
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
The next thing to configure will be your minimal web application context for Spring.
The spring config file is
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<context:component-scan base-package="com.springmvc" />
<tx:annotation-driven />
<bean id="jspViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="dataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.springmvc.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.connection.pool_size">${hibernate.connection.pool_size}</prop>
</props>
</property>
</bean>
<bean id="transactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
With Spring having introduced schema based configuration in Spring 2.0, it greatly reduces the amount of XML verbosity in your configuration file, hence this minimal web application context.
The context:property-placeholder element which we use to tell the Spring container where to find some properties files for resolving ${} type placeholders within our application context.
The context:component-scan element that tells Spring where to begin scanning our package for annotated components like @Repository, @Service, @Controller, etc. Using this element also automatically implies the context:annotation-config element’s behavior to scan for things like @Autowired and several other annotations. Therefore you don’t need both elements in your application context.
The tx namespace is responsible for handling our database transactions. Using the tx:annotation-driven element, we’re telling Spring to look for beans annotated with @Transactional and handle them according to the parameters defined in those annotations. You’ll also notice on line 58, we’ve defined a TransactionManager implementation bean that gets automatically wired into our annotated configuration for handling the transactions. Because we named our TransactionManager simply “transactionManager” in our configuration, it automatically gets wired into our annotated configuration, this is the Spring default. If we had given it a different name, we would have had to add the transaction-manager attribute to the tx:annotation-driven element and specify the id of our TransactionManager implementation bean.
Our TransactionManager defines one property named sessionFactory, which references our sessionFactory bean. Our sessionFactory bean is required for Hibernate and more importantly, being an AnnotationSessionFactoryBean, it will allow us to annotate domain objects at the code level, rather than define our mappings to the database tables in separate mapping XML files. We define Hibernate specific properties within our configuration file, rather than in a hibernate configuration XML file.
The parameters within the ${} place-holders can be accessed from a properties file. Just make sure that you dropped your properties file somewhere in the classpath.
One of the main reasons for using Hibernate is to persist domain objects to a datasource without the need for writing ugly SQL statements, acquiring connections and cleaning up those connections, etc. Hibernate does this for you.
A Simple class definition for User entity
package com.springmvc.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "USER")
public class User {
@Id @GeneratedValue
@Column(name = "USER_ID" )
private Long id;
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
public User() {}
public Long getId() {
return id;
}
private void setId ( Long id ) {
this.id = id;
}
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;
}
}
Integrating Hibernate with Spring, the standard JPA annotations work just as well and that’s what I’m using here.
First we’ve annotated the class with @Entity which tells Hibernate that this class represents an object that we can persist.
The @Table(name = “USER”) annotation tells Hibernate which table to map properties in this class to.
The first property in this class is our object ID which will be unique for all events persisted. This is why we’ve annotated it with @Id. The @GeneratedValue annotation says that this value will be determined by the datasource, not by the code. Lastly the @Column(name = “USER_ID”) annotation is used to map this property to the USER_ID column in the USER table. The other two properties are annotated in the same fashion, but merely with the @Column attribute.
Here is our simple Controller implementation for a Controller which handles User registration and viewing it back.
package com.springmvc.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.springmvc.model.User;
import com.springmvc.service.UserService;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView addUser ( @ModelAttribute("user") Event event) {
return new ModelAndView ( "userAdd" );
}
@RequestMapping(method = RequestMethod.GET)
public ModelAndView viewUsers() {
Map model = new HashMap();
model.put ( "users", userService.getAllUsers() );
return new ModelAndView ( "userView", model );
}
}
I’ve annotated the UserController class with @Controller and @RequestMapping(“/users”) on line 18 and 19. When Spring scans our package, it will recognize this bean as being a Controller bean for processing requests. The @RequestMapping annotation tells Spring that this Controller should process all requests beginning with /users in the URL path. That includes /users/* and /users.html.
An UserService bean will be autowired and injected by Spring since we applied the @Autowired annotation to the private property. The property name is important because Spring will look for a bean named userService to inject.
The first method named addUser is annotated with @RequestMapping(value = “/add”, method = RequestMethod.GET). The annotation tells Spring that requests to /users/save.html should be processed by this method, but only if the request method is GET. The method signature annotates one of the parameters with @ModelAttribute(“users”) which has to do with our JSP page. The important part of this method is the userService.addUser ( user ). This is a call to our service bean to add our domain object to the datasource when it’s entered in the browser. It returns a ModelAndView object to resolve the view by logical name. Lets say it redirect to /users.html, which will also be handled by this Controller.
The next method viewUsers is basically our default method when a simple GET request is made to /users.html, you can see this by the annotation @RequestMapping(method = RequestMethod.GET) . This method creates a Map and adds the data to the map by invoking the userService.getAllUsers() method. That call returns a List object. The method returns another ModelAndView object, but this time it will try to resolve to a view named userView and the data model is being passed back to the browser so we can access the data within the JSP. The logical view name will resolve to “/WEB-INF/jsp/userView.jsp” when processed by the jspViewResolver configured in the application context.
Next main thing is, having the Business layer. Here comes our ServiceImpl
package com.springmvc.service;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.springmvc.dao.EventDao;
import com.springmvc.model.User;
@Service("userService")
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
public UserServiceImpl() {}
@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void addUser(User user) {
userDao.saveUser ( user );
}
public List<Event> getAllUsers() {
return usertDao.getAllUsers();
}
}
This service bean implements the UserService interface which provides our contract of what this implementation will do.
The class is annotated with @Service(“userService”). This is the meta data that Spring will use when autowiring the userService property in the Controller created in the previous step. We’ve explicitly defined the name “userSerivice” in the annotation’s value, otherwise without it Spring would have named the bean “userServiceImpl” automatically and the autowiring of this bean in the Controller and other classes would have failed.
The @Transactional(propagation=Propagation.SUPPORTS, readOnly=true) annotation will be recognized by the tx:annotation-driven element in the application context. Having placed the annotation at the class level means that all methods in this class by default should adhere to these transaction rules. propagation=Propagation.SUPPORTS means a transaction isn’t necessary, but if one exists, then the method will run in that transaction. The readOnly=true attribute is pretty straight forward, by default all data retrieved should be read only. No writes to the datasource are permitted.
An EventDao object gets autowired. That class will deal with the actual ORM framework, in this case, Hibernate.Another @Transactional annotation has been applied at the method level. This time @Transactional(propagation=Propagation.REQUIRED, readOnly=false) tells the transaction manager that this method requires a transaction. This is defined by the propagation=Propagation.REQUIRED attribute. The readOnly=false attribute overrides the class level readOnly=true so that we are permitted to write to the datasource. That’s an important thing to keep in mind. When you annotate at the class level, the rules are applied to every method, but if you need to override the class level attributes, you can do so by annotating the methods in question, overriding whatever attributes you need to. In this case, since the method will write to the datasource, we require a transaction and write permissions.
below is our HibernateDAO Implementation
package
com.springmvc.dao
; import java.util.Date; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.springmvc.dao.User; @Repository("userDao") public class HibernateEventDao implements EventDao { @Autowired private SessionFactory sessionFactory; public void saveEvent ( Event event ) { sessionFactory.getCurrentSession().saveOrUpdate ( event ); } @SuppressWarnings("unchecked") public List<Event> getAllEvents() { return (List<Event>) sessionFactory.getCurrentSession().createCriteria ( Event.class ).list(); } }
asasasa
The @Repository(“userDao”) meta data tells Spring this class is a DAO object and Spring should name it “userDao” so that it can be properly autowired into the userService bean from the previous step.The Hibernate SessionFactory will be autowired by Spring. If you remember, the SessionFactory was defined in the application context with the bean id “sessionFactory” and thus Spring will autowire into this property since it has the same name with the @Autowired annotation.The saveUser method is defined. It interacts with the session factory by getting the current Hibernate Session and calling the saveOrUpdate method, passing in the User object that was passed to the method. If the User object has an existing USERID, Hibernate will attempt to update that record in the datasource, if it’s not found, it will try to insert it.The listUserdefines the DAO method for retrieving existing Events from the datasource. It only contains 1 simple line. First the current Session is retrieved from the SessionFactory, and then a Criteria is created from that Session, into which we simply pass the User.class common name, followed by a call to list(). So what we’ve done is essentially told Hibernate, select all records from the table that User.class is mapped to, and return all property values of the User class in the form of a java.util.List object.
The next part is view. Here we create a file userView.jsp to display all the available users.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="css/styles.css"></link>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Existing Events</title>
</head>
<body>
<h1>Existing Users</h1>
<br /><br />
<c:if test="${!empty user}">
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Date</th>
</tr>
<c:forEach items="${users}" var="user">
<tr>
<td><c:out value="${user.username}" /></td>
<td><c:out value="${user.password}" /></td>
</tr>
</c:forEach>
</table>
</c:if>
<c:if test="${empty username}">
No username found in the Database
</c:if>
</body>
</html>
Next thing would be creating userAdd.jsp page to add a new user
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Add Event</title>
</head>
<body>
<h1>Add User</h1>
<c:url var="viewUsersUrl" value="/users.html" />
<a href="${viewUsersUrl}">View All Users</a>
<br /><br />
<c:url var="addUserUrl" value="/users/save.html" />
<form:form modelAttribute="user" method="POST" action="${addUserUrl}">
<form:label path="username">Username:</form:label>
<form:input path="username"/><br />
<form:label path="password">Password:</form:label>
<form:input path="password"/><br />
<input type="submit" value="Save User" />
</form:form>
</body>
</html>
No need to define these JSP pages assuming that you’ve a basic knowledge of JSTL.The only important thing to note here was the mapping names. Note that the Mapping we made using Annotations at Controller must match in the JSP pages. Otherwise it’ll not retrieve or do any process. This is a simple Hibernate-Spring Integration project by me. I hadn’t used any ORM’s before and with Hibernate, i am sure that i’m pretty much impressed. Atleast i get rid of those annoying long SQL sentences.
I’d prefer NetBeans over Eclipse as it comes bundled with Spring and Hibernate Framework Support, which means saving a lot of time. It’ll create you the POJO mapping files and everything easily. The Spring 3.0 Module for NetBeans is available for download.
Source : http://jpgmr.wordpress.com/2009/12/08/spring-mvc-and-hibernate-made-simple-with-annotations/
I’ve downloaded the code from the above link and used it as the base for my project.
发表评论
-
Java深度历险(九)——Java安全
2012-05-11 04:54 997安全性是Java应用程序的非功能性需求的重要组成部分,如同其它 ... -
Hibernate 3 Annotations 进阶
2012-04-28 02:54 1037安装 Hibernate Annotations为了使用Hib ... -
Spring MVC3 Hibernate CRUD Sample Application
2012-04-24 04:12 2240To learn any web framework star ... -
spring mvc 2
2011-09-27 19:39 1650视图解析器 spring mvc的action返回的是一个逻辑 ... -
spring mvc
2011-09-27 19:20 1127spring-mvc 如图 请求首先通过DispatcherS ... -
JDK反射之JDK动态proxy
2011-09-26 20:18 2393JDK动态代理 JDK 动 ...
相关推荐
这是谷歌三大论文之一的 MapReduce: Simplified Data Processing on Large Clusters 英文原文。我的翻译可以见https://blog.csdn.net/m0_37809890/article/details/87830686
struts2.2.3+spring3.0.3+hibernate3.6.7整合jar包 +配置文件+整合Struts2.2与Hibernate3.6需要的Spring3.1相关JAR文件.doc+SSM config.xml.doc+mybatis-spring-1.0.0-reference-simplified-chinese.pdf
当需要输入中文时,使用Chinese(Simplified) IME - Ime/Nonlme Toggle进行语言切换。 **2. Ctrl+Shift+Space:** 显示上下文信息(Context Information)。 **3. 双击空格键:** 输入空格。 --- #### 五、定位与...
MapReduce 编程模型简介 MapReduce 是一种编程模型,由 Jeffrey Dean 和 Sanjay Ghemawat 于 2004 年提出,用于处理大规模数据集的分布式计算。该模型将计算任务分解成两个主要阶段:Map 和 Reduce。...
《MapReduce: Simplified Data Processing on Large Clusters》这篇论文由Google的研究员Jeffrey Dean和Sanjay Ghemawat撰写,旨在介绍一种名为MapReduce的分布式计算模型。在MapReduce出现之前,Google和其他公司...
在 Atom 中,选择【Install】,然后搜索要安装的扩展,选择 simplified-chinese-menu 插件,点击【Install】安装。安装完成后,Atom 将自动转换成中文版。 四、Atom 的扩展 Atom 自带了类似于 WordPress 安装扩展...
MyBatis+3+User+Guide+Simplified+Chinese中文文档
书籍标题《Signal and Power Integrity:simplified》和其描述指出了几个重要的知识点和概念,这些通常涉及电子工程和印刷电路板(PCB)设计领域。 首先,从标题和描述中,我们可以了解到书籍的作者是Eric Bogatin,...
provides a rich ecosystem of projects to address modern application needs, like security, simplified access to relational and NoSQL datastores, batch processing, integration with social networking ...
ignal and Power Integrity - Simplified (2nd Edition) Signal and Power Integrity - Simplified (2nd Edition) 作者: Eric Bogatin 出版社: Prentice Hall PTR 副标题: Simplified 出版年: 2009-07-27 页数: ...
一般推荐将配置文件、映射文件、实体类、DAO类、Service层和服务实现层分开存放,遵循MVC(Model-View-Controller)设计模式,使代码结构清晰,易于理解和维护。 通过以上概述,我们可以看出,MyBatis不仅提供了...
Core.Animation:Simplified Animation Techniques for Mac and iPhone Development 第八张 OpenGL Layer的demo,找了很多,发现下载的都不能跑起来,于是自己把下载来的修改了一番,现在都可以跑起来了,发出来和...
阅读提供的PDF文档《MyBatis-3-User-Guide-Simplified-Chinese.pdf》和《mybatis-spring-1.0.0-reference-simplified-chinese.pdf》将有助于更深入地理解MyBatis的用法以及如何在Spring环境中集成MyBatis。...
MapReduce的翻译,我只是个搬运工qwq
在使用Inno-Setup-Chinese-Simplified-Translation-6.1.0这个压缩包时,你需要先安装Inno Setup的基础版本,然后将中文语言包解压并覆盖到相应的语言文件夹,即可切换到中文界面。这样,无论是创建安装脚本还是调试...
SD Host Controller Simplified Specification Version 3.00(简化版规范3.00)是SD卡协会(SD Association)发布的标准文档,该版本在早期规范的基础上增加了对高级直接内存访问(Advanced DMA)、测试寄存器和64位...
Google那篇著名的论文的ppt,MapReduce开山之作,介绍了Google对MapReduce的实现。
在提供的资源文件`MyBatis-3-User-Guide-Simplified-Chinese.pdf`中,详细介绍了MyBatis的使用方法和配置,包括动态SQL、结果映射、参数映射等内容,这些对于理解MyBatis如何与Spring和MySQL协同工作至关重要。...