论坛首页 Java企业应用论坛

不总结就得付出代价

浏览 7138 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2010-03-06   最后修改:2010-03-06
    好久没有去研究Hibernate了,过去的东西已经全忘。今天拾起来时我付的代价非常之大,最终根源在于没有总结以往的开发经验,异常非常之熟悉确不能快速锁定问题源。我就以下面几几个问题做为切入点来总结一下,这块里所涉及到的知识点。

    问题列表:
    1,分组查询
    2,left outer join/right outer join/full outer join/inner outer join区别


问题1:分组查询
    分组查询不就是group by嘛,确实是这样。但是在hibernate里面查出来的数据就不一样,我所有指的定是每列数据。例如:
    I)HQL(Hibernate Query Language)
 
  from SysUser user group by userId

    使用HQL查询出来的是符合条件,所有字段的数据
    II)QBC(Query By Criteria)
    DetacheCriteria dc = DetachedCriteria.forClass(SysUser.class);
    dc.setProjection(Projections.groupProperty("this.userId"));
    List<SysUser> list = sysUserService.findByCriteria(dc);

    这段码看上去没有一点错,我们还是用后面打印的SQL语句来说话吧。这里我就手工模拟写出后台打印SQL语句,其实意思是一样。
   
select this_.user_id from sys_user this_ group by this_.user_id

    看完这一段SQL语句,你还认为上面代码没有错吗?相信你一眼就可以看会出现什么样的问题:ClassCastException这个异常会抛出来。问题出来那总得有解决方案吧,肯定是有的。具体怎么选择那你自己的事了。
    方案一(不推荐):直接用SQL查询
    方案二:是用示例查询
    select new SysUser(user.userId,user.name) from SysUser user group by user.userId;

    这样查底的前提是SysUser类中必须有一个SysUser(userId,name)构造方法
    方案三:直接返回对象,这又是什么意思呢?看下面代码就知道意思啦
 
  select user from SysUser user group by user.userId

   
    查询这样的简单的表不用费多大劲。下面再看看一个复杂点的表结构。
@Entity
@Table(name = "doc_document")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DocDocument implements java.io.Serializable {

	private static final long serialVersionUID = 8811969619989885931L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "doc_document_id")
	private Integer docDocumentId;
	
	@OneToMany(mappedBy = "docDocument")
	private Set<DocReceiveApprove> docReceiveApproves = new HashSet<DocReceiveApprove>(
			0);
	@OneToMany(mappedBy = "docDocument")
	private Set<DocFbTotal> docFbTotals = new HashSet<DocFbTotal>(0);
	@OneToMany(mappedBy = "docDocument")
	private Set<DocSend> docSends = new HashSet<DocSend>(0);
	@OneToMany(mappedBy = "docDocument")
	private Set<DocAttach> docAttachs = new HashSet<DocAttach>(0);
	@OneToMany(mappedBy="docDocument")
	private Set<DocDocumentReturn> docDocumentReturns = new HashSet<DocDocumentReturn>(0);
	//@Fetch(FetchMode.SELECT)
	@OneToMany(mappedBy="docDocument")
	private Set<DocDocumentUser> dcDocumentUsers = new HashSet<DocDocumentUser>(0);
	
........
}

@Entity
@Table(name = "doc_document_user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DocDocumentUser implements java.io.Serializable {

	private static final long serialVersionUID = 8811969619989885931L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "doc_document_user_id")
	private Integer docDocumentUserId;
	private Integer isflow;
	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE})
	@JoinColumn(name = "doc_document_id")
	private DocDocument docDocument;
	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
	@JoinColumn(name = "user_id")
	private CommonUser commonUser;
.........
}

@Entity
@Table(name="common_user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class CommonUser implements java.io.Serializable {

	private static final long serialVersionUID = 6147253484121456257L;
	@Id
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @JoinColumn(name = "user_id")
	private Integer userId;//用户ID
	
	//@Fetch(FetchMode.SELECT)
	@OneToMany(mappedBy="commonUser")
	private Set<DocDocumentUser> dcDocumentUsers = new HashSet<DocDocumentUser>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocFbTotal> docFbTotals = new HashSet<DocFbTotal>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocReceiveApproveCheck> docReceiveApproveChecks = new HashSet<DocReceiveApproveCheck>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocReceiveinfoHst> docReceiveinfoHsts = new HashSet<DocReceiveinfoHst>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocRrSend> docRrSends = new HashSet<DocRrSend>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocReceiveApproveDraw> docReceiveApproveDraws = new HashSet<DocReceiveApproveDraw>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<InfoSender> infoSenders = new HashSet<InfoSender>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<DocPrintTrackHst> docPrintTrackHsts = new HashSet<DocPrintTrackHst>(0);
	@OneToMany(mappedBy="commonUser")
	private Set<LogOperation> logOperations = new HashSet<LogOperation>(0);
......
}

      代码就贴一部分,可以达到理解的用途就行。
      下面方法的目录还是按组查询:
	public List<DocDocument> getWaitDocument() {
		 DetachedCriteria dc = DetachedCriteria.forClass(DocDocument.class);
		 dc.createCriteria("dcDocumentUsers", "ddu");
		 dc.setFetchMode("ddu", FetchMode.SELECT);
		 dc.add(Restrictions.eq("ddu.dealstatus", "1"));
		 dc.createCriteria("ddu.commonUser", "user");
		 dc.add(Restrictions.eq("user.userCode", "111"));
		 dc.setProjection(Projections.groupProperty("this.docDocumentId"));
		 List<DocDocument> list = this.documentService.findByCriteria(dc);
}

      好啦,问题源肯定不用说就可以看出来啦。
      如果我想得到DocDocument对象的某个Set集合对象,我想方案一/方案二全部用不上了。但是方案三就得改造一下,如下:
     
String hql = "select doc from DocDocument as doc left join doc.dcDocumentUsers as ddu  left join ddu.commonUser as user group by doc.docDocumentId order by doc.docDocumentId desc";

     好啦问题总算解决啦。
     总结一下,我们的解决方案用的就是下一个问题所要提到的东西。那咱们就进入第二个问题讲解。
     首先我们得了解一下,left outer join/right outer join/full outer join/inner outer join的工作原理。
    
引用

假设a表和b表的数据是这样的。
a b
id name  id stock 
1  a 1 15
2 b 2 50
3 c  

select * from a inner join b on a.id=b.id
这个语法是连接查询中的内连接,它产生的结果是
两个表相匹配的记录出现在结果列表中。
根据上面的表,出现的结果是这样的
a.id name b.id stock
1   a 1 15
2 b 2 50
----------------------------
select * from a,b where a.id=b.id
这个语法是内连接的另外一种写法,其执行结果与inner join 一样

--------------------------------

select * from a left/right join b on a.id=b.id
这个是外连接语法中的左外连接或右外连接
如果是左外连接的话,它将显示a表的所有记录,
select a.*,b.* from a left join b on a.id=b.id
查询的结果是这样的:
a.id name b.id stock
1   a 1 15
2 b 2 50
3 c null null 
--------------------------------------------
如果是右外连接的话,它将显示b表的所有记录,
select a.*,b.* from a right join b on a.id=b.id
查询的结果是这样的:
a.id name b.id stock
1   a 1 15
2 b 2 50

  
     知道原理了就知道为什么在每一个问题上面要修改一下方案三(因为查询语句返回的是三个对象的数据,也就是说三张表的数据,所以通过select doc可以得到结果)。
     讲到这里截取两张Hibernate注解API文档的图片来讲解一下抓取策略。




     今天就总结这两个问题
   


   
  • 大小: 52.2 KB
  • 大小: 87 KB
   发表时间:2010-03-08   最后修改:2010-03-08
说实话我没看懂,或许我太笨,

QBC
    DetacheCriteria dc = DetachedCriteria.forClass(SysUser.class);
    dc.setProjection(Projections.groupProperty("this.userId"));
    List<SysUser> list = sysUserService.findByCriteria(dc);

出错问题的根本在于,数据库中不会允许类似下面的SQL
  select * from t_city group by province_id


那么我要问下
  from SysUser user group by userId

这句HQL到底想得到什么?
0 请登录后投票
   发表时间:2010-03-08   最后修改:2010-03-08
指定了分组字段 但是没有指定要汇总的字段?
0 请登录后投票
   发表时间:2010-03-08  
下面这句确实意图不明确,没有汇总语句,在HIBERNATE中也是无法执行的,楼主有没有弄错?
xuzhfa123 写道

 
from SysUser user group by userId


0 请登录后投票
   发表时间:2010-03-13   最后修改:2010-03-13
mlw2000 写道
说实话我没看懂,或许我太笨,

QBC
    DetacheCriteria dc = DetachedCriteria.forClass(SysUser.class);
    dc.setProjection(Projections.groupProperty("this.userId"));
    List<SysUser> list = sysUserService.findByCriteria(dc);

出错问题的根本在于,数据库中不会允许类似下面的SQL
  select * from t_city group by province_id


那么我要问下
  from SysUser user group by userId

这句HQL到底想得到什么?

from SysUser user group by user.userId
不好意思,漏了个别名,这个跟上面提出的问题还没有太大的关联。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics