文章40 | 阅读 20120 | 点赞0
在上一讲中,我们已经学会了Hibernate-5.0.7、Struts-2.3.24和Spring-4.2.4这三个框架的整合。现在,我在其基础上讲解两个知识点,一个是Spring中Hibernate模板的使用,一个是使用Spring如何解决延迟加载问题。温馨提示:如果有小伙伴没看过前一讲,那么接下来你就别扯蛋了,劝你回去看看。
在Spring和Hibernate整合的过程中,Spring提供了一个Hibernate的模板类(即HibernateTemplate类),它可以用来简化Hibernate部分的开发,它有点类似于Spring的JDBC模板类。正是由于Hibernate的模板类对Hibernate框架进行了封装,所以我们可以直接调用Hibernate的模板类里面的方法实现对数据库表的CRUD操作。
在这一小节中,我会使用HibernateTemplate模板类来完成CRUD的操作,主要是对s2sh_crm数据库中的cst_customer表进行增删改查。
上一讲中我们一直演示的就是添加操作,顺便完成了CRM系统中保存客户的功能,所以这里不再赘述,只是看一下咱使用了HibernateTemplate模板类里面的什么方法。
首先,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
}
package com.meimeixia.ssh.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl类中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
}
然后,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
}
package com.meimeixia.ssh.dao.impl;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl类中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
}
从以上update方法中可以看出,咱使用了HibernateTemplate模板类里面的update方法。
首先,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
}
package com.meimeixia.ssh.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
@Override
public void delete(Customer customer) {
customerDao.delete(customer);
}
}
然后,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
}
package com.meimeixia.ssh.dao.impl;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
}
从以上delete方法中可以看出,咱使用了HibernateTemplate模板类里面的delete方法。
HibernateTemplate模板类里面提供了两个方法来根据ID查询出一个对象并返回,它们分别是:
但在这里,我会使用get方法。为了演示该方法,首先,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
}
package com.meimeixia.ssh.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
@Override
public void delete(Customer customer) {
customerDao.delete(customer);
}
@Override
public Customer findById(Long cust_id) {
return customerDao.findById(cust_id);
}
}
然后,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
}
package com.meimeixia.ssh.dao.impl;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
//查询一个
@Override
public Customer findById(Long cust_id) {
return this.getHibernateTemplate().get(Customer.class, cust_id);
}
}
从以上findById方法中可以看出,咱使用了HibernateTemplate模板类里面的get方法。
HibernateTemplate模板类里面提供了三种方式来查询出所有对象并返回List集合,它们分别是:
下面,我会详细地介绍一下这三种方式。先来看第一种方式,即HQL检索方式。首先,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
}
package com.meimeixia.ssh.service.impl;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
@Override
public void delete(Customer customer) {
customerDao.delete(customer);
}
@Override
public Customer findById(Long cust_id) {
return customerDao.findById(cust_id);
}
@Override
public List<Customer> findAllByHQL() {
return customerDao.findAllByHQL();
}
}
然后,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
}
package com.meimeixia.ssh.dao.impl;
import java.util.List;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
//查询一个
@Override
public Customer findById(Long cust_id) {
return this.getHibernateTemplate().get(Customer.class, cust_id);
}
//查询所有,使用HQL
@Override
public List<Customer> findAllByHQL() {
//使用HQL
List<Customer> list = (List<Customer>) this.getHibernateTemplate().find("from Customer");
return list;
}
}
从以上findAllByHQL方法中可以看出,咱使用了HibernateTemplate模板类里面的find方法。
第一种方式(即HQL检索方式)介绍完后,再来介绍第二种方式(即QBC检索方式)。首先,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
List<Customer> findAllByQBC();
}
package com.meimeixia.ssh.service.impl;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
@Override
public void delete(Customer customer) {
customerDao.delete(customer);
}
@Override
public Customer findById(Long cust_id) {
return customerDao.findById(cust_id);
}
@Override
public List<Customer> findAllByHQL() {
return customerDao.findAllByHQL();
}
@Override
public List<Customer> findAllByQBC() {
return customerDao.findAllByQBC();
}
}
然后,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
List<Customer> findAllByQBC();
}
package com.meimeixia.ssh.dao.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
//查询一个
@Override
public Customer findById(Long cust_id) {
return this.getHibernateTemplate().get(Customer.class, cust_id);
}
//查询所有,使用HQL
@Override
public List<Customer> findAllByHQL() {
//使用HQL
List<Customer> list = (List<Customer>) this.getHibernateTemplate().find("from Customer");
return list;
}
//查询所有,使用QBC
@Override
public List<Customer> findAllByQBC() {
//离线查询条件对象,理应从外部传递进来
DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
List<Customer> list = (List<Customer>) this.getHibernateTemplate().findByCriteria(criteria);
return list;
}
}
在以上findAllByQBC方法中,离线查询条件对象本应从web层中传递进来,但为了避免麻烦,这里直接new了一个离线查询条件对象。
第二种方式(即QBC检索方式)介绍完后,再来介绍第三种方式(即命名检索方式)。首先,将HQL语句先定义出来,那么问题来了,这个HQL语句到底定义在什么位置呢?如果你有映射配置文件,那么当前的HQL操作是针对哪一个实体进行操作的,就在哪一个实体的映射配置文件中进行声明,声明就像下面这样。
然后,修改service层中的接口和实现类。
package com.meimeixia.ssh.service;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的业务层的接口 * @author liayun * */
public interface CustomerService {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
List<Customer> findAllByQBC();
List<Customer> findAllByNamedQuery();
}
package com.meimeixia.ssh.service.impl;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 客户管理的业务层的实现类 * * @author liayun * */
@Transactional //在业务层使用注解
public class CustomerServiceImpl implements CustomerService {
// 注入Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public void save(Customer customer) {
System.out.println("CustomerServiceImpl中的save方法执行了......");
customerDao.save(customer);
}
@Override
public void update(Customer customer) {
customerDao.update(customer);
}
@Override
public void delete(Customer customer) {
customerDao.delete(customer);
}
@Override
public Customer findById(Long cust_id) {
return customerDao.findById(cust_id);
}
@Override
public List<Customer> findAllByHQL() {
return customerDao.findAllByHQL();
}
@Override
public List<Customer> findAllByQBC() {
return customerDao.findAllByQBC();
}
@Override
public List<Customer> findAllByNamedQuery() {
return customerDao.findAllByNamedQuery();
}
}
接着,修改dao层中的接口和实现类。
package com.meimeixia.ssh.dao;
import java.util.List;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的接口 * @author liayun * */
public interface CustomerDao {
void save(Customer customer);
void update(Customer customer);
void delete(Customer customer);
Customer findById(Long cust_id);
List<Customer> findAllByHQL();
List<Customer> findAllByQBC();
List<Customer> findAllByNamedQuery();
}
package com.meimeixia.ssh.dao.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.ssh.dao.CustomerDao;
import com.meimeixia.ssh.domain.Customer;
/** * 客户管理的Dao层的实现类 * @author liayun * */
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
System.out.println("CustomerDaoImpl中的save方法执行了......");
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
//查询一个
@Override
public Customer findById(Long cust_id) {
return this.getHibernateTemplate().get(Customer.class, cust_id);
}
//查询所有,使用HQL
@Override
public List<Customer> findAllByHQL() {
//使用HQL
List<Customer> list = (List<Customer>) this.getHibernateTemplate().find("from Customer");
return list;
}
//查询所有,使用QBC
@Override
public List<Customer> findAllByQBC() {
//离线查询条件对象,理应从外部传递进来
DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
List<Customer> list = (List<Customer>) this.getHibernateTemplate().findByCriteria(criteria);
return list;
}
@Override
public List<Customer> findAllByNamedQuery() {
/* * 命名查询:首先先定义一个hql,给这个hql起个名,然后我们就可以通过这个名字来进行查询了。 */
return (List<Customer>) this.getHibernateTemplate().findByNamedQuery("queryAll");
}
}
首先在src目录下新建一个com.meimeixia.ssh.test包,然后在该包下新建一个S2SHDemo01的单元测试类,其内容如下,可以看出我们是通过Spring来整合JUnit进行单元测试的。
package com.meimeixia.ssh.test;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.meimeixia.ssh.domain.Customer;
import com.meimeixia.ssh.service.CustomerService;
/** * 记得引入spring-test-4.2.4.RELEASE.jar * @author liayun * */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class S2SHDemo01 {
@Resource(name="customerService")
private CustomerService customerService;
//测试修改操作
@Test
public void demo01() {
Customer customer = customerService.findById(1l);
customer.setCust_name("来福");
customerService.update(customer);
}
//测试删除操作
@Test
public void demo02() {
Customer customer = customerService.findById(1l);
customerService.delete(customer);
}
//测试查询所有的操作,使用HQL的方式
@Test
public void demo03() {
List<Customer> list = customerService.findAllByHQL();
for (Customer customer : list) {
System.out.println(customer);
}
}
//测试查询所有的操作,使用QBC的方式
@Test
public void demo04() {
List<Customer> list = customerService.findAllByQBC();
for (Customer customer : list) {
System.out.println(customer);
}
}
//测试查询所有的操作,使用命名的方式
@Test
public void demo05() {
List<Customer> list = customerService.findAllByNamedQuery();
for (Customer customer : list) {
System.out.println(customer);
}
}
}
接着,你可以运行以上一系列的单元测试方法进行测试,看Hibernate的模板类好不好使,我相信以上测试都能通过,是没什么问题的!
在我们做一些查询操作的时候,极有可能会出现一个延迟加载的问题,这个延迟加载的问题其实在Hibernate那个地方就已经有了,但Hibernate并没有给出具体的解决方案,而在Spring里面就提供了延迟加载问题的解决方案。
在SSH整合开发中哪些地方会出现延迟加载这个问题呢?下面揭晓答案。
延迟加载问题产生的原因是因为我们关联的对象默认都是采用延迟加载这种策略。
为了演示延迟加载这个问题是怎样出现的,我们需要修改一下CustomerDaoImpl实现类的代码,让其根据ID查询一个对象并返回时,调用Hibernate模板类的load方法。
然后,在CustomerAction类中添加如下一个findById方法。
最后,发布咱们的项目到Tomcat服务器中,在浏览器地址栏中输入http://localhost:8080/S2SH02/customer_findById.action这个的URL地址进行访问,这时你就会看到报了一个no-session异常。
这时,Spring就提供了一个延迟加载问题的解决方案,即使用OpenSessionInViewFilter过滤器来解决延迟加载问题。想要使用这个OpenSessionInViewFilter过滤器,我们还得在web.xml文件配置一把。
使用了该过滤器,将会在视图层中开启session,也就是说会在Action中获得到session(这时session是线程绑定的),当然了,session的关闭也是在web层这边。然后业务层拿到线程绑定的session,再开启事务…,即事务还是在业务层这边。一句话,会在web层中开启或关闭session。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://liayun.blog.csdn.net/article/details/100593605
内容来源于网络,如有侵权,请联系作者删除!