不总结就得付出代价

好久没有去研究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的工作原理。
[quote]
假设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
[/quote]

知道原理了就知道为什么在每一个问题上面要修改一下方案三(因为查询语句返回的是三个对象的数据,也就是说三张表的数据,所以通过select doc可以得到结果)。
讲到这里截取两张Hibernate注解API文档的图片来讲解一下抓取策略。
[img]http://dl.iteye.com/upload/attachment/213351/ecd51758-f445-3263-acc8-e1e4f035c8c9.bmp[/img]

[img]http://dl.iteye.com/upload/attachment/213353/fb109d3f-fa4d-3589-8636-5fd20dc8e22b.bmp[/img]

今天就总结这两个问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值