准备好了单元测试模块,就写个底层的数据访问的控制Handle类来试试吧。也就是通常我们所说的DAO类。一般而言,每个模型/实体类需要建立一个DAO类。 不过经验告诉我们,一些通用的CRUD方法几乎在每个DAO类中都是一样的,那么也就是说我们通常所写的DAO会有些代码冗余的问题,而且根据业务需要,日后的维护工作有可能添加一些新的实体类,写地越多,DAO类就越多,写的代码就越多余还浪费时间。如何将写好的一个DAO类进行代码重用成为了问题。其实笔者见过一个的系统里有做过将Hibernate框架人应用做成静态类,用到时直接HibernateUtil.save()的。今天,咱也做一个通用的DAO放一些通用的CRUD方法进去,用来做通用的CRUD操作。这样做既省去了不少代码量,加强了代码可读性,而且还方便快捷地架构起这个WebModel,可以重用到很多的系统中。当然,遇到特殊的Entity 需要建个别的DAO时再当别论。
首先是接口的编写,我在接口的编写时加了很多的JavaDoc,就不贴出代码了,上传为附件方便读者下载吧。此处列出几个方法做简单说明
package com.xxxxx.webmodel.pin;
import java.util.List;
import java.util.Map;
public interface IPersistencePin {
public void createPersistingEntity(Object persistingObj) throws Exception;
public <PerE> PerE retrievePersistedEntity(Class<PerE> persistedClass,
long id) throws Exception;
public <PerE> PerE retrievePersistedEntity(Class<PerE> persistedClass,
String identifier) throws Exception;
public <PerE> List<PerE> retrievePersistedEntityAllInList(
Class<PerE> persistedClass) throws Exception;
public void updatePersistedEntity(Object persistingObj) throws Exception;
public void deletePersistedEntity(Object persistingObj) throws Exception;
}
接口的实现:
package com.xxxxx.webmodel.pin.impl;
/*省略多个import 语句*/
import com.gxino.webmodel.pin.IPersistencePin;
@Repository
public class HibernatePersistencePin implements Serializable,IPersistencePin {
private static final long serialVersionUID = -295800418896667101L;
private SessionFactory sessionFactory;
public static long getSerialversionuid() {
return serialVersionUID;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
其中,第一个方法 createPersistingEntity(Object persistingObj) 将Map到Hibernate 中的任意Pojo的对象持久化,即将某实体类的一个对象的各项属性值存入数据库。
@Override
public void createPersistingEntity(Object persistingObj) throws Exception {
Session session = null;
boolean needCloseSession = false;
try{
session = sessionFactory.getCurrentSession();
if(session==null)throw new HibernateException("No current Session");
}catch(HibernateException he){
session = sessionFactory.openSession();
needCloseSession = true;
}
try{
session.save(persistingObj);
if(needCloseSession)session.close();
}catch(HibernateException he){
throw new Exception("Save Pojo failed, because of "+he.getMessage());
}
}
笔者在该方法中做了currentSession与openSession双处理,也就是说该方法既可以是业务逻辑进行事务中的某一句,也可以无事务信赖地被单独调用。后面的update 方法与delete方法以及通过id从数据库中查出该对象的方法是如出一辙,只是session.save(persistingOjb)换成其他语句,就不贴代码了。贴一下另两个方法的第二个Try块中的代码吧:
1,<PerE> PerE retrievePersistedEntity(Class<PerE> persistedClass,
String uniquePropertyName, Object propertyValue)
传入一个唯一键值的名值对找出类对象:
Criteria criteria = session.createCriteria(persistedClass);
criteria.add(Restrictions.eq(uniquePropertyName, propertyValue));
@SuppressWarnings("unchecked")
PerE result = (PerE)criteria.uniqueResult();
if(needCloseSession)session.close();
return result;
这里用到了Hibernate的Criteria与Restrictions,其实还有个Example类。 关于这一点,网络上有好多高手有解盲它的专题用法的帖子,笔者就不作大篇文章说它了。感觉这个比起写hql更 『面向对象』 一点儿,好用且易理解,所以特意贴在这里一个,以提醒自己与读者们可以这样去写。其实用了它的代码都是白话文,简单提一下: 从Session中创建一个某pojo人“基准”,用一些 “条件”,或是举例的方式,限定这个查询基准,之后按这个限定的标准查出具体对象。
查找所有对象到一个List中也不多说了,criteria不add任何限制,直接criteria.list();就好.
2,<PerE> PerE retrievePersistedEntity(Class<PerE> persistedClass,
String identifier) throws Exception;吧
无需给出唯一键的名,只需要唯一键的值,即去查询到该实体类对象。不过由于一个表中,可能有多个唯一键,这样就会产生冲突。例如,用户名和Email两个唯一性字段,用户A用aaa@aaa.com作用户名,用户B用aaa@aaa.com作email,这种情况下查询到用户的结果就不仅是A而且还有B了。所以笔者将它在接口里就标了@deprecated。
同样,只贴第二个try块中应放的代码。
String propertyName=null;
Method[] methodArray =persistedClass.getMethods();
if(methodArray!=null)for(Method method:methodArray){
if(method.getName().startsWith("get")){
Criteria criteria = session.createCriteria(persistedClass);
Annotation anno = method.getAnnotation(Column.class);
if(anno.toString().contains("unique=true")){
propertyName = Character.toString(method.getName().charAt(3)).toLowerCase()+method.getName().substring(4);
criteria.add(Restrictions.eq(propertyName, identifier));
}
@SuppressWarnings("unchecked")
PerE result = (PerE)criteria.uniqueResult();
if(needCloseSession)session.close();
return result;
}
}
if(needCloseSession)session.close();
return null;
这方法的实现需要javax.persistence.Column这一注解到实体类中的每一个属性做配合。换句话说,Hibernate的Mapping是注解方式的。 Column注解在JPA的规范中, hibernate框架有JPA的实现,在hibernate-jpa-2.0-api-x.x.x-Final.jar包中。 上面代码用到了反射,主要意思是:找到该Pojo类中所有属性的getter,通过查看该getter上是否注解有@Column并且注解的一个属性unique值为true,来找到相应的属性名,然后用名值对限定查询标准去查出实体类对象。
至于怎么用JPA注解配置Pojo,也可以作为专题发表一篇文章了,笔者就不多叙述,直接在附件夹带一些实体类了,实体类如何map到sessionFactory中也在第一篇《xxx 注解化配置》的ApplicationContext.java中出现,代码在配置sessionFactory 的@Bean的方法中:
@SuppressWarnings("rawtypes")
Class[] entities = new Class[2];
entities[0] = AccountEntity.class;
entities[1] = ActionLogEntity.class;
asfBean.setAnnotatedClasses(entities);
另外,有些读者可能已经发现,上述通用DAO中的实现中,每个方法也几乎重用了好多地方,只是改变了中间的核心部分,可不可以用一个固定的方法将每个方法的核心语句包住,就像是让Spring代管Transactional一样,很明显,我们会想到AOP,顺便将log也做到AOP中,不过这一篇就不多讨论了。先就这样用着。
最后,别忘了写单元测试类。
package com.xxxxx.webmodel.test.pin;
import static org.junit.Assert.fail;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
import com.xxxxx.webmodel.entity.AccountEntity;
import com.xxxxx.webmodel.entity.ActionLogEntity;
import com.xxxxx.webmodel.pin.IPersistencePin;
import com.xxxxx.webmodel.util.ApplicationContext;
import com.xxxxx.webmodel.util.WebConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ApplicationContext.class})
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class })
@TransactionConfiguration(defaultRollback=true,transactionManager="hibernateTransactionManager")
@Transactional
public class PersistencePinTest {
private IPersistencePin persistPin;
private Map<String,Object> usedStuff;
public IPersistencePin getPersistPin() {
return persistPin;
}
@Resource
public void setPersistPin(IPersistencePin persistPin) {
this.persistPin = persistPin;
}
@BeforeClass
public static void init() throws Exception{
new WebConfiguration().onStartup(null);
}
@Before
public void setUp() throws Exception{
if(usedStuff==null)
usedStuff = new HashMap<String,Object>();
AccountEntity account = new AccountEntity();
account.setUserName("junittest");
account.setPassword("junittest");
account.setEmail("junittest@junit.com");
account.setAlias("unitTest");
account.setAge((short)18);
account.setGender("Male");
account.setCreatedAt(new Date());
persistPin.createPersistingEntity(account);
usedStuff.put("userId", new Long(account.getId()));
usedStuff.put("userName", account.getUserName());
usedStuff.put("userEmail", account.getEmail());
ActionLogEntity actionLog = new ActionLogEntity();
actionLog.setAction("Junit Test");
actionLog.setActor(account);
actionLog.setHappenTime(new Date());
try{persistPin.createPersistingEntity(actionLog);}
catch(Exception e){
e.printStackTrace();
}
usedStuff.put("actionId", new Long(actionLog.getId()));
usedStuff.put("actionTime", actionLog.getHappenTime());
}
@Test
@Ignore
public final void testHibernateSession() throws Exception{
/*Please not execute @Before setUp() method, for test this, and NO @TransactionConfiguration NO @Transactional*/
/*Also make other test methods @Ignore*/
AccountEntity account = new AccountEntity();
account.setUserName("junittest");
account.setPassword("junittest");
account.setEmail("junittest@junit.com");
account.setAlias("unitTest");
account.setAge((short)18);
account.setGender("Male");
account.setCreatedAt(new Date());
persistPin.createPersistingEntity(account);
persistPin.deletePersistedEntity(account);
}
}
具体的其他测试方法在附件的文件中,或是读者们自行去写会比笔者的要好很多。
附件中有源码,在很下面哦,请您仔细找一下
分享到:
相关推荐
Java EE Web Application Primer Building Bullhorn A Messaging App with JSP, Servlets, JavaScript, Bootstrap and Oracle 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请...
Build a Twitter-like web application called Bullhorn using Java, Oracle, and more Create web applications using Eclipse Design web pages with HTML forms, tables, and more Use SQL along with Java ...
Digital Java EE 7 Web Application Development 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
Prepare for the Pivotal Certified Spring Web Application Developer exam and learn about Spring MVC DispatcherServlet configuration, Spring MVC programming model essentials, Spring MVC views and form ...
Java EE Web Application Primer Building Bullhorn A Messaging App with JSP, Servlets, JavaScript, Bootstrap and Oracle 英文无水印原版pdf pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和...
用java开发Arcgis server 9.2 web application
Encapsulating security requirements for web development with the Java programming platform, Secure Java: For Web Application Development covers secure programming, risk assessment, and threat ...
信息: Deploying web application directory lx01 2010-11-11 22:52:05 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory blog 2010-11-11 22:52:06 org.apache....
java application实现的在线聊天类
WebApplication1.zip
Web压力测试工具 web application stress tool 1.1
有关JavaApplet和JavaApplication一些介绍
Web Application Design
Ext.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application ...
Java Web编程宝典-十年典藏版.pdf 是PDF电子书,不是源码。共分2个包。 《Java Web编程宝典(十年典藏版)》是一本集技能、范例、项目和应用为一体的学习手册,书中介绍了应用Java Web进行程序开发的各种技术、技巧。...
Apress.Java.EE.Web.Application.Primer.pdf 版本,javaWeb方向入门的书
Web Application Stress Tool,微软官方的.web压力测试工具
Microsoft Web Application Stress Tool算是比较好用的windows平台的并发测试工具,欢迎下载.(包含安装说明)