项目的底层查询关联到3层(action,service,dao),每一层都有各自不同的任务,下面贴上示意图(我们这里以这句SQL查询语句为例子)
SELECT o.textName,o.textRemark FROM elec_text o 放置到DAO层
WHERE o.textName LIKE '%张%' 放置到Service层
AND o.textRemark LIKE '%李%'
ORDER BY o.textDate DESC , o.textName ASC
下面就开始从TestService中创建一个模拟的action:
<span style="font-size:18px;">@Test
public void findCollection() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml");
IElecTextService iElecTextService=(IElecTextService) applicationContext.getBean(ElecTextServiceImpl.SERVICE_NAME);
ElecTextForm elecTextForm=new ElecTextForm();
elecTextForm.setTextName("晕晕");
elecTextForm.setTextRemark("没什么事情!");
List<ElecText> list = iElecTextService.findCollectionByConditionNoPage(elecTextForm);
}</span>
当创建findCollectionByConditionNoPage这行代码的时候,编译器就会提示需要在IElecTextService中创建对应的方法所以我们直接创建。
<span style="font-size:18px;">public interface IElecTextService {
public final static String SERVICE_NAME="cn.itcast.elec.service.impl.ElecTextServiceImpl";
public void saveElecText(ElecText elecText);
public List<ElecText> findCollectionByConditionNoPage(
ElecTextForm elecTextForm);
}</span>
在这个接口中创建完具体的方法后就需要在其实现类中创建实现方法下面:(这一层我们具体完成的任务就是讲service层的hql语句完成,特别需要注意的就是hql语句之间的空格宁可多不能少,不然会报错)
<span style="font-size:14px;">@Transactional(readOnly=true)//方法级别的事务覆盖了类级别的事务,只有增删改的事务我才定义成可写,其他的事务我定义成只读
@Service(IElecTextService.SERVICE_NAME)
public class ElecTextServiceImpl implements IElecTextService {
@Resource(name=IElecTextDao.SERVICE_NAME)
//@resource意思是以注解的形式依赖注入:
//spring的作用就是解耦,但是如果使用注解的形式依赖注入的话,就会使java代码耦合,
//所以更推荐使用xml文件来管理bean
private IElecTextDao elecTextDao;
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED,readOnly=false)
public void saveElecText(ElecText elecText){
elecTextDao.save(elecText);
}
public List<ElecText> findCollectionByConditionNoPage(
ElecTextForm elecTextForm) {
//组织Hql语句
/**
* SELECT o.textName,o.textRemark FROM elec_text o 放置到DAO层
WHERE o.textName LIKE '%张%' 放置到Service层
AND o.textRemark LIKE '%李%'
ORDER BY o.textDate DESC , o.textName ASC
*
*
*/
String hqlWhere="";
List<String> paramsList=new ArrayList<String>();
if(elecTextForm!=null && org.apache.commons.lang.StringUtils.isNotBlank(elecTextForm.getTextName())){
hqlWhere+="and o.textName like ?";
paramsList.add("%"+elecTextForm.getTextName() +"%");
}
if(elecTextForm!=null && org.apache.commons.lang.StringUtils.isNotBlank(elecTextForm.getTextRemark())){
hqlWhere+="and o.textRemark like ?";
paramsList.add("%"+elecTextForm.getTextRemark()+"%");
}
Object [] params=paramsList.toArray();
//下面组织orderby语句
LinkedHashMap<String, String> orderby=new LinkedHashMap<String, String>();
orderby.put("o.textDate","DESC");
orderby.put("o.textName","ASC");
//查询列表
List<ElecText> list=elecTextDao.findCollectionByConditionNoPage(hqlWhere,params,orderby);
for(int i=0;list!=null&& i<list.size();i++){
ElecText elecText = list.get(i);
System.out.println(elecText.getTextName()+" "+elecText.getTextRemark());
}
return null;
}
</span>
下面List<ElecText> list=elecTextDao.findCollectionByConditionNoPage(hqlWhere,params,orderby);这句代码会提示你需要在ICommonDao层建立findCollectionByConditionNoPage这个方法ok,下面我们到DAO层:
<span style="font-size:14px;">public interface ICommonDao<T> {
public void save(T entity);
public void update(T entity);
//返回的是一个对象所以使用T
T findObjectByID(Serializable id);
void deleteObjectByID(Serializable[] ids);
void deleteObjectByCollection(List<T> entities);
List<T> findCollectionByConditionNoPage(String hqlWhere,
Object[] params, LinkedHashMap<String, String> orderby);
}</span><span style="color:#ff0000;font-size:18px; ">
</span>
OK下面我们实现接口的findCollectionByConditionNoPage方法:
<span style="font-size:14px;">public List<T> findCollectionByConditionNoPage(String hqlWhere,
final Object[] params, LinkedHashMap<String, String> orderby) {
//组织hql语句
String hql="from elec_text o where 1=1 ";
String hqlOrderBy="";
hqlOrderBy=" order by";
//遍历map取出元素
for(Map.Entry<String, String> entry : orderby.entrySet()){
hqlOrderBy+=" "+entry.getKey()+" "+entry.getValue()+",";
}
hqlOrderBy=hqlOrderBy.substring(0,hqlOrderBy.length()-1);
hql=hql+hqlWhere+hqlOrderBy;
final String Hql=hql;
@SuppressWarnings("unchecked")
List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException,
SQLException {
org.hibernate.Query query = session.createQuery(Hql);
for(int i=0;params!=null&&i<params.length;i++){
query.setParameter(i, params[i]);
}
return query.list();
}
});
return null;
}
</span>
到这里我们的条件查询就快结束了,返回到第一段java代码,使用junit测试一下!
这个方法有很多的细节需要注意,知识点也比较的多,比如:LinkedHashMap的知识,map的遍历,spring的hibernate模板使用,字符串的拼接,泛型的使用,以及注解的使用等等。。。这个方法很通用大家都可以拿过去用,还有很多需要改进的地方,比如加入分页,再将一些比较长的方法进行封装等等。。