- 浏览: 236240 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
-
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 955一、内存溢出类型 ... -
Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 2.Spring MVC REST
2011-03-27 00:03 3243前言 :本文只阐述如何使用Spring MVC做REST应用 ... -
传说中的投票系统
2011-03-15 02:35 0传说中的投票系统 -
Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 1.序
2011-03-14 21:37 2686屈指算算,做J2EE开发已经有超过5个年头有多了,技术的东西跟 ... -
If..else, Map, Enum查询速度对比
2011-03-04 23:27 1664习惯每天逛一下论坛,今天发现一个关于重构的帖子 http:/ ... -
[转]Java虚拟机(JVM)参数配置说明
2010-09-16 22:54 1130Java虚拟机(JVM)参数配置说明 在J ... -
使用StringBuffer和StringBuilder代替String的+运算
2010-05-05 16:14 1281使用StringBuffer和StringBuilder代替S ... -
String.split()和StringTokenizer和indexOf()的比较
2010-05-05 15:52 6240将字符串按照一定的规 ... -
【转】Java中的UDP协议编程
2010-03-04 00:38 1757一. UDP协议定义 UDP ... -
iBatis异常There is no statement named update in this SqlMap.
2009-10-26 09:39 4567最近使用iBatis搭建项目架构的时候遇到了一个异常,如下文所 ... -
Spring配置iBatis多个SqlMapConfig.xml
2009-10-23 15:42 4185Spring粘合iBatis的时候需要配置iBatis的Sql ... -
Javamail在解析附件是抛出Missing start boundary异常
2009-09-04 17:45 9647在做javamail通过pop3解析邮件的时候,在解析邮件包含 ... -
Javamail 的AuthenticationFailedException异常
2009-09-04 10:43 2309Javamail接收用pop3协议接收邮件的时候,我们可以通过 ... -
Spring 定时器使用
2009-07-15 14:36 2717【原文】http://nighthun.itpub.net/p ... -
字符串转化为unicode编码
2009-04-28 11:42 1601字符串转化为unicode编码 package com ... -
SFTP上传和下载
2008-05-06 15:24 8759维护一个旧项目(eJMS),先前从JDK1.3升级到1.5,后 ... -
项目由OC4J 9i升级到OC4J10g
2008-04-27 18:45 1515最近项目eJMS需要由oc4j 9 ... -
Java日积月累001-字符串比较的技巧,避免NullPointerException
2008-04-16 23:33 1344这里说的String的比较是value的比较,通过equals ... -
Tomcat设置Session time out的时间
2007-04-11 11:48 3971在Tomcat中的conf/web.xml可以找到以下scri ... -
动态配置log4j
2007-09-04 11:10 3997看到好的文章,收录以备学习之用。文章来源于http://www ...
相关推荐
标题 "Spring3 MVC REST + JPA2 (Hibernate 3.6.1) 构建投票系统 - 2.Spring MVC REST" 提供了我们要探讨的核心技术栈:Spring 3 MVC、RESTful API 和 JPA2(这里指的是 Hibernate 3.6.1 实现)。在这个项目中,开发...
1.3.2 基于SVN库持续构建Spring源码 1.4 小结 2 控制反转容器 2.1 DI及Spring DI概述 2.1.1 面向Java ME/Java SE的BeanFactory 2.1.2 面向Java EE的ApplicationContext 2.2 多种依赖注入方式 2.2.1 设值注入 ...
11.11.2 解决方案 472 11.11.3 工作原理 472 11.12 使用GORM查询 475 11.12.1 问题 475 11.12.2 解决方案 475 11.12.3 工作原理 475 11.13 创建自定义标记 477 11.13.1 问题 477 11.13.2 解决方案...
11.11.2 解决方案 472 11.11.3 工作原理 472 11.12 使用GORM查询 475 11.12.1 问题 475 11.12.2 解决方案 475 11.12.3 工作原理 475 11.13 创建自定义标记 477 11.13.1 问题 477 11.13.2 解决方案...