当前位置:Gxlcms > 数据库问题 > 【SSH项目实战05】完成数据库的级联查询和分页

【SSH项目实战05】完成数据库的级联查询和分页

时间:2021-07-01 10:21:17 帮助过:28人阅读

        首先在CategoryService接口中定义该方法:

public interface CategoryService extends BaseService<Category> {
	//查询类别信息,级联管理员
	public List<Category> queryJoinAccount(String type); //使用类别的名称查询
}
        然后我们在CategoryService的实现类CategoryServiceImpl中实现这个方法:

@Service("categoryService")
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {

	@Override
	public List<Category> queryJoinAccount(String type) {
		String hql = "from Category c where c.type like :type";
		return getSession().createQuery(hql)
				.setString("type", "%" + type + "%").list();
	}
}
        在两个Model中我们配一下关联注解:

//Category类中
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "account_id")
public Account getAccount() {
	return this.account;
}
//Account类中
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "account")
public Set<Category> getCategories() {
    return this.categories;
}
        然后我们在测试类中测试一下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:beans.xml")
public class CategoryServiceImplTest {

	@Resource
	private CategoryService categoryService;
	
	@Test
	 public void testQueryJoinAccount() {
 		for(Category c : categoryService.queryJoinAccount("")) {
			 System.out.println(c);
			 System.out.println(c.getAccount());
 		}
 	}
}

2. 级联查询存在的问题

        我们看一下控制台的输出可以看出,它发了不止一条SQL语句,但是我们明明只查询了一次,为什么会发这么多语句呢?这就是常见的1+N问题。所谓的1+N问题,就是首先发出一条语句查询当前对象,然后发出N条语句查询关联对象,因此效率变得很低。这里就两个对象,如果有更多的对象,那效率就会大打折扣了,我们该如何解决这个问题呢?

        可能大家会想到将fetch设置生FetchType.LAZY就不会发多条语句了,但是这肯定不行,因为设置成LAZY后,我们就拿不到Account对象了,比较好的解决方法是我们自己写hql语句,使用join fetch。具体看修改后的CategoryServiceImpl实现类:

@Service("categoryService")
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {

	@Override
	public List<Category> queryJoinAccount(String type) {
		String hql = "from Category c left join fetch c.account where c.type like :type";
		return getSession().createQuery(hql)
				.setString("type", "%" + type + "%").list();
	}
}
        left join表示关联Account一起查询,fetch表示将Account对象加到Category中去,这样就只会发一条SQL语句了,并且返回的Category中也包含了Account对象了。

3. 完成分页功能

        Hibernate中的分页很简单,只需要调用两个方法setFirstResult和setMaxResults即可:我们修改一下CategoryService接口和它的实现类CategoryServiceImpl:

//CategoryService
public interface CategoryService extends BaseService<Category> {
	//查询类别信息,级联管理员
	public List<Category> queryJoinAccount(String type, int page, int size); //并实现分页
}

//CategoryServiceImpl
@Service("categoryService")
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {

    @Override
    public List<Category> queryJoinAccount(String type, int page, int size) {
        String hql = "from Category c left join fetch c.account where c.type like :type";
        return getSession().createQuery(hql)
                .setString("type", "%" + type + "%")
                .setFirstResult((page-1) * size) //从第几个开始显示
                .setMaxResults(size) //显示几个
                .list();
    }
}
        我们在测试类中测试一下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:beans.xml")
public class CategoryServiceImplTest {

	@Resource
	private CategoryService categoryService;

	@Test
	public void testQueryJoinAccount() {
		for(Category c : categoryService.queryJoinAccount("",1,2)) { //显示第一页,每页2条数据
			System.out.println(c + "," + c.getAccount());
		}
	}
}
        为此,我们写完了Service的方法了,完成了对商品类别的级联查询和分页功能。

       (注:到最后我会针对此项目申请博客专栏,并提供整个项目的源码下载!欢迎大家收藏或关注)

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!

-----更多文章请看:http://blog.csdn.net/eson_15


【SSH项目实战05】完成数据库的级联查询和分页

标签:

人气教程排行