- 浏览: 234161 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
test_lockxxx:
mythal 写道不好意思,StringUtils.split ...
String.split()和StringTokenizer和indexOf()的比较 -
grantbb:
受用,支持!
Javamail 发送附件中文名乱码问题解决 -
kensunhu:
for(File attach:attachments){
...
Javamail 发送附件中文名乱码问题解决 -
Ben.Sin:
liupeng_10408 写道博主,你好!我开发的是andr ...
Javamail读取邮件列表出现OutOfMemery -
liupeng_10408:
博主,你好!我开发的是android版邮件系统。
只写了如下几 ...
Javamail读取邮件列表出现OutOfMemery
Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 3. JPA2(Hibernate实现)
- 博客分类:
- Java
上一篇介绍了如何使用Spring MVC搭建REST的web应用,今天主要介绍如何使用JPA2.0实现数据库操作
JPA2.0只是一种规范,实现的框架有多种,包括几个较为常用的:
- TopLink - Sun
- OpenJPA - Apache
- Hibernate - Jboss
当然还有更多其它的实现框架,但这些不是本文讨论的范围。
以前用得最多的iBatis框架,后来因为工作的关系开始学习使用Hibernate,所以这次就是用Hibernate框架来完成JPA的应用。
闲话少说,我们来关注一下如何使用JPA来完成我们的后台业务逻辑。我们先从Domain开始
- Domain
以下使用用户表User作为例子,他对应数据库表为
T_USER(*USER_OID, VERSION_NO, USER_NAME, PASSWORD, NICK_NAME, GENDER)
Java代码如下:
package ben.vote.domain; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import ben.vote.domain.type.Gender; @Entity @Table(name = "T_USER") public class User implements Serializable{ private static final long serialVersionUID = 8787093968860546113L; private Long userOid; private Long versionNo; private String userName; private String nickName; private String password; private Gender gender; @Id @GeneratedValue @Column(name="USER_OID", unique=true, nullable=false) public Long getUserOid() { return userOid; } public void setUserOid(Long userOid) { this.userOid = userOid; } @Version @Column(name="VERSION_NO") public Long getVersionNo() { return versionNo; } public void setVersionNo(Long versionNo) { this.versionNo = versionNo; } @Column(name="USER_NAME", length=40, unique=true, nullable=false) public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Column(name="NICK_NAME", length=80, unique=true, nullable=false) public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } @Column(name="PASSWORD", length=80, nullable=false) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Embedded @Column(name="GENDER", length=1) public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } }
这里只使用了一小部分的annotation,其他的annotation就不一一列举了,有需要大家查相关文档。
类User里面用到的Annontation很简单,而且也很好理解,除了其中两个需要稍作说明,其他就不一一描述了
@Version 声明这列用于版本控制,使用的是VersionNo乐观锁
@Embbeded 声明此列和枚举类Gender相关联
枚举类Gender有三种类型,分别是Male和Female,还有Other(我们要尊重性别选择),代码如下:
package ben.vote.domain.type; public enum Gender { M("Male"), F("Female"), O("Other"); private Gender(String value){ this.value = value; } private String value; public String getValue(){ return value; } }
- Service
下一步我们构建Service来实现domain是数据库的交互。先定义一个接口ICURDService,具体如下
package ben.vote.service; import java.util.List; import java.util.Map; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Transactional public interface ICRUDService<E> { void create(E domain); void delete(E domain); E update(E domain); @Transactional(propagation=Propagation.NOT_SUPPORTED, readOnly = true) E query(Class<E> c, Long id); @Transactional(propagation=Propagation.NOT_SUPPORTED, readOnly = true) List<E> query(Class<E> c, Map<String, Object> params); @Transactional(propagation=Propagation.NOT_SUPPORTED, readOnly = true) List<E> queryAll(Class<E> c); }
顾名思义,这个接口主要声明的服务是C reate, R etrieve, U pdate, D elete。
@Transactional 表示这个接口类将由Spring来管理事务
而由于查询类没有事务的必要,所以也是用annontation来解除事务
- propagation=Propagation.NOT_SUPPORTED 表示与事务无关
- readOnly表示只读
有了接口我们就可以开始编写实现类,具体如下
package ben.vote.service.impl; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.stereotype.Service; import ben.vote.service.ICRUDService; //@Service(value="crudService") public class CRUDServiceImpl<E> implements ICRUDService<E>{ @PersistenceContext protected EntityManager entityManager; public void create(E entity) { entityManager.persist(entity); } public void delete(E entity) { entityManager.remove(entity); } public E query(Class<E> c, Long id) { return entityManager.find(c, id); } @SuppressWarnings("unchecked") public List<E> queryAll(Class<E> c) { final String HQL = "from " + c.getSimpleName(); return entityManager.createQuery(HQL).getResultList(); } @SuppressWarnings("unchecked") public List<E> query(Class<E> c, Map<String, Object> params) { if (null == params || params.isEmpty()) { return queryAll(c); } else { StringBuilder queryBuilder = new StringBuilder() .append("from ") .append(c.getSimpleName()) .append(" o where "); Set<String> keys = params.keySet(); //Where int count = 0; for (String key : keys){ if (count > 0) { queryBuilder.append(" and "); } else { count ++; } queryBuilder.append("(").append(key).append(" = :").append(key).append(")"); } Query query = entityManager.createQuery(queryBuilder.toString()); for (String key : keys){ query.setParameter(key, params.get(key)); } return query.getResultList(); } } public E update(E entity) { return entityManager.merge(entity); } }
可以看出,这个类写得简陋的来也相当的丑陋,见笑了。
@Service(name="crudService") 是我用来做Unit test用的,这里可以没有这个必要
到这里Service基本上完成了,和接口一样,实现类只保留了泛型,并没有指向具体的Domain,具体的还是由业务来声明
- Controller
上一篇已经知道如何使用Spring MVC构建Web的REST应用,这里就沿用上一篇的内容,添加一个用户Controller
package ben.vote.web; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import ben.vote.domain.User; import ben.vote.domain.type.Gender; import ben.vote.service.ICRUDService; @Controller public class UserController { @Autowired private ICRUDService<User> userService; /** * Access GET request forward to register form * * @return */ @RequestMapping(value="/register", method=RequestMethod.GET) public String register(){ return "/register/form"; } /** * Access POST request the register a new User * * @param request * @param response * @return */ @RequestMapping(value="/register", method=RequestMethod.POST) public String register(HttpServletRequest request, HttpServletResponse response) { String userName = request.getParameter("userName"); String password = request.getParameter("password"); String rePassword = request.getParameter("rePassword"); String nickName = request.getParameter("nickName"); String gender = request.getParameter("gender"); //Validation before save boolean hasException = false; if (userName == null || "".equals(userName.trim())){ request.setAttribute("userNameException", "Please fill in User Name!"); hasException = true; } else if (isExistsUser("userName", userName)) { request.setAttribute("userNameException", "User is exists!"); hasException = true; } //Password & re-password should not be null if (password == null || "".equals(password.trim())){ request.setAttribute("passwordException", "Please fill in Password!"); hasException = true; } if (rePassword == null || "".equals(rePassword.trim())){ request.setAttribute("rePasswordException", "Please fill in Re-Password!"); hasException = true; } //Password and re-password should be the same if (!password.equals(rePassword)){ request.setAttribute("rePasswordException", "Password are not equals!"); hasException = true; } if (nickName == null || "".equals(nickName.trim())){ request.setAttribute("nickNameException", "Please fill in Name!"); } else if (isExistsUser("nickName", nickName)) { request.setAttribute("nickNameException", "Nick name is exists!"); hasException = true; } //Handle exception if (hasException) { request.setAttribute("userName", userName); request.setAttribute("nickName", nickName); request.setAttribute("gender", gender); return register(); } User user = new User();; user.setUserName(userName); user.setPassword(password.trim()); user.setNickName(nickName); user.setGender(Gender.valueOf(gender)); //Save the user userService.create(user); //Put user into session request.getSession().setAttribute("logonUser", user); //Redirect to success page return "redirect:/register/success"; } /** * Access GET request forward to register form * * @return */ @RequestMapping(value="/register/success", method=RequestMethod.GET) public String registerSuccess() { return "/register/success"; } /** * Validate the specific user is exists or not * * @param key the column name * @param value the column value * @return */ private boolean isExistsUser(String key, String value) { Map<String, Object> params = new HashMap<String, Object>(); params.put(key, value); List<User> userList = userService.query(User.class, params); return (userList != null && !userList.isEmpty()); } }
Controller准备好了之后,接下来就可以编写jsp了,首先我们看看页面的样子
Form 源代码如下
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <html> <head> <%@include file="../include/INC.HEADER.jspf" %> </head> <body> <div class="titlebar"> <span class="title">Vote</span> <span class="sub-title"> - User Registration</span> </div> <div class="title-option"> <a href="<%=basePath%>/login">Login</a> </div> <hr/> <div style="color: red">${registerException}</div> <form action="register" method="POST"> <table> <tr> <td class="label">User Name *</td> <td> <input type="text" name="userName" value="${userName}"/> <span style="color: red">${userNameException}</span> </td> </tr> <tr> <td class="label">Password *</td> <td> <input type="password" name="password" value="${password}"/> <span style="color: red">${passwordException}</span> </td> </tr> <tr> <td class="label">Re-Password *</td> <td> <input type="password" name="rePassword" value="${rePassword}"/> <span style="color: red">${rePasswordException}</span> </td> </tr> <tr> <td class="label">Name *</td> <td> <input type="text" name="userName" value="${userName}"/> <span style="color: red">${userNameException}</span> </td> </tr> <tr> <td class="label">Gender</td> <td> <select name="gender" value="${gender}"> <option value="M">Male</option> <option value="F">Female</option> <option value="O">Other</option> </select> </td> </tr> <tr> <td align="right"><input type="submit" name="submit" value="Submit"/></td> <td><input type="reset" name="reset" text="Reset"/></td> </tr> </table> </form> </body> </html>
填入注册资料后点击Submit
成功页面JSP script
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <html> <head> <%@include file="../include/INC.HEADER.jspf" %> </head> <body> <div class="titlebar"> <span class="title">Vote</span> <span class="sub-title"> - User Registration</span> </div> <div class="title-option"> <a href="<%=basePath%>/login">Login</a> </div> <hr/> <div>Thanks your register, ${logonUser.nickName}</div> </body> </html>
查看数据库资料
可以看到用户注册成功
View -> Controller -> Service -> DB这一流程基本上就完成了。用户登录就不详细了,具体可以参考本章的源代码
下一章将介绍如何实现投票
上一篇:Spring3 MVC REST + JPA2 (Hibernate 3.6.1)构建投票系统 - 2.Spring MVC REST
发表评论
-
【转】Java Out of Memory 分析
2013-08-02 00:55 938一、内存溢出类型 ... -
Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 2.Spring MVC REST
2011-03-27 00:03 3227前言 :本文只阐述如何使用Spring MVC做REST应用 ... -
传说中的投票系统
2011-03-15 02:35 0传说中的投票系统 -
Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 1.序
2011-03-14 21:37 2672屈指算算,做J2EE开发已经有超过5个年头有多了,技术的东西跟 ... -
If..else, Map, Enum查询速度对比
2011-03-04 23:27 1624习惯每天逛一下论坛,今天发现一个关于重构的帖子 http:/ ... -
[转]Java虚拟机(JVM)参数配置说明
2010-09-16 22:54 1110Java虚拟机(JVM)参数配置说明 在J ... -
使用StringBuffer和StringBuilder代替String的+运算
2010-05-05 16:14 1264使用StringBuffer和StringBuilder代替S ... -
String.split()和StringTokenizer和indexOf()的比较
2010-05-05 15:52 6214将字符串按照一定的规 ... -
【转】Java中的UDP协议编程
2010-03-04 00:38 1735一. UDP协议定义 UDP ... -
iBatis异常There is no statement named update in this SqlMap.
2009-10-26 09:39 4550最近使用iBatis搭建项目架构的时候遇到了一个异常,如下文所 ... -
Spring配置iBatis多个SqlMapConfig.xml
2009-10-23 15:42 4171Spring粘合iBatis的时候需要配置iBatis的Sql ... -
Javamail在解析附件是抛出Missing start boundary异常
2009-09-04 17:45 9608在做javamail通过pop3解析邮件的时候,在解析邮件包含 ... -
Javamail 的AuthenticationFailedException异常
2009-09-04 10:43 2290Javamail接收用pop3协议接收邮件的时候,我们可以通过 ... -
Spring 定时器使用
2009-07-15 14:36 2703【原文】http://nighthun.itpub.net/p ... -
字符串转化为unicode编码
2009-04-28 11:42 1582字符串转化为unicode编码 package com ... -
SFTP上传和下载
2008-05-06 15:24 8730维护一个旧项目(eJMS),先前从JDK1.3升级到1.5,后 ... -
项目由OC4J 9i升级到OC4J10g
2008-04-27 18:45 1486最近项目eJMS需要由oc4j 9 ... -
Java日积月累001-字符串比较的技巧,避免NullPointerException
2008-04-16 23:33 1328这里说的String的比较是value的比较,通过equals ... -
Tomcat设置Session time out的时间
2007-04-11 11:48 3943在Tomcat中的conf/web.xml可以找到以下scri ... -
动态配置log4j
2007-09-04 11:10 3982看到好的文章,收录以备学习之用。文章来源于http://www ...
相关推荐
标题 "Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 2.Spring MVC REST" 提供了我们要探讨的核心技术栈:Spring 3 MVC、RESTful API 和 JPA2(这里指的是 Hibernate 3.6.1 实现)。在这个项目中,开发...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码 hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码
`hibernate-jpa-2.1-api-1.0.0.final.jar`是Hibernate对JPA 2.1规范的实现库,它使得开发者能够使用Hibernate的高效功能同时遵循JPA规范。 **1. Hibernate与JPA的关系** Hibernate最初作为一个独立的ORM框架,后来...
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar官方下载,请放心使用
hibernate-jpa-2.0-api-1.0.1.Final-sources.jar hibernate jpa 源代码
java.lang.NoClassDefFoundError: javax/persistence/spi/ProviderUtil 或javax/persistence/entitylistener问题
4. `org.hibernate.boot.model`和`org.hibernate.boot.model.source`:这两个包包含了模型构建和源代码解析的相关类,用于构建实体类的元模型,是Hibernate映射的基础。 5. `org.hibernate.boot.registry`:这部分...
java运行依赖jar包
"spring3+springmvc+jpa+hibernate多数据源"是一个示例项目,它演示了如何在一个应用中集成Spring 3、Spring MVC、JPA 2.0以及Hibernate,以实现对多个数据源的支持。下面将详细介绍这些技术及其集成的关键点。 **...
本篇文章将重点围绕“hibernate-jpa-2.1-api-1.0.0.final-sources.jar.zip”这一压缩包,深入解析Hibernate对JPA 2.1 API的实现,以期帮助读者深入理解其内部机制。 JPA(Java Persistence API)是Java平台上的一个...
在IT领域,构建高效、可扩展的Web应用是至关重要的,而"spring+springMVC+jpa+hibernate框架整合"就是一个常见的解决方案。这个整合涉及到四个关键的技术栈:Spring框架、SpringMVC、JPA(Java Persistence API)...
在本教程中,我们将深入探讨如何使用Spring MVC、Spring和Hibernate三大框架进行全注解的整合开发。这个视频教程系列的第11部分,重点可能是建立在前几部分的基础之上,进一步深化对这三个核心技术的理解和实践。 ...
包含hibernate所有所需jar包还有一些其他包日志包、jpa支持包等: 列如:hibernate-core-5.1.0.Final.jar hibernate-ehcache-5.1.0.Final.jar hibernate-entitymanager-5.1.0.Final.jar hibernate-envers-5.1.0....
5. **Integration with ORMs**:Spring Data JPA 可以与各种 JPA 实现(如 Hibernate、EclipseLink 等)配合使用,为不同的 ORM 解决方案提供统一的编程模型。 6. **Custom Query Methods**:开发者可以定义自己的...
在本项目中,我们看到的是一个基于 Spring 4.2 版本的综合构架,结合了 Spring MVC、Spring Data 和 JPA,以及 Hibernate 的使用。这些技术的整合为构建高效、可维护的 web 应用提供了强大的支持。 1. **Spring 4.2...