这里我会以上一篇文所的的预定义的表,请对照着阅读:一些Hibernate的用法笔记(1)
在一些实际的开发环境中,我们查询一张表,可能需要关联到另外一张表的信息,不是那种已经存在于数据库表的字段中的数据,可能是需要统计的一些数据,例如我需要知道这个用户在系统下面到底有多少中角色,写成SQL可能是
1 2 3 4 5 |
select {ac.*}, (select count(*) from account_role_rel where account_role_rel.account_id=ac.id) role_count from account ac where ac.id=? |
对于像上述查询语句中,这种查出来为纯数字的变量,而且不存在于实体当中的变量,我们可以通过addScalar的方式捕获出来
那么我们在DAO中转换当前SQL语句查询结果的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SQLQuery q = session.createSQLQuery( "select {ac.*}," + "(select count(*) from account_role_rel where account_role_rel.account_id=ac.id) role_count " + "from account ac " + "where" + "ac.id=1" ); q.addEntity("ac", AccountModel.class); //可以通过StandardBasicTypes设置额外捕获的参数的类型 q.addScalar("role_count", StandardBasicTypes.INTEGER); //获取到的内容为Object[]{AccountModel, role_count} return q.uniqueResult(); |
StandardBasicTypes里面有很多基本类型:
还记得我们之前声明的用户和角色的关联表:
account_role_rel | ||
列名 | 类型 | 注释 |
id | INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT | 递增标识 |
account_id | INT(11) NOT NULL | 用户ID |
role_id | INT(11) NOT NULL | 角色ID |
现在我们需要声明AccountRoleRelModel.java,我需要在里面Join上RoleModel和AccountModel的实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * 用户与角色的关联表的实体 */ @Entity @Table(name = "account_role_rel") public class AccountRoleRelModel { private Integer id; private AccountModel account; private RoleModel role; @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getId() { returnn this.id; } @OneToOne //这里可以改成ManyToOne,相对,下面的JoinColumn需要加上insertable=false, updatable=false @JoinColumn(name = "account_id", referencedColumnName = "id") public AccountModel getAccount() { return this.account; } @OneToOne @JoinColumn(name = "account_id", referencedColumnName = "id") public RoleModel getRole() { return this.role; } //setter省略 } |
这种时候,我们在编写DAO的时候,我们可以通过addJoin加入对应实体的映射:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
@Repository() public class AccountRoleRelDAO { @PersistenceContext public EntityManager em; @Transactional(readOnly = true) public List<Object[]> getCashAccount(int accountId) { Session session = em.unwrap(Session.class); SQLQuery q = session.createSQLQuery( "select {account_role_rel.*}," + "{account.*}," + "{role.*} " + "from account_role_rel " + "inner join role on " + "role.id=account_role_rel.role_id " + "inner join account on " + "account.id=account_role_rel.account_id " + "where account_role_rel.account_id=:accountId" ); q.setParameter("accountId", accountId); q.addEntity("account_role_rel", AccountRoleRelModel.class); /* public abstract SQLQuery addJoin(String tableAlias, String path) * Declare a join fetch result. * Parameters: * tableAlias - The SQL table alias for the data to be mapped to this fetch * path - The association path ([owner-alias].[property-name]). */ //根据上述定义,addJoin的第一个参数,应该是需要join的表在SQL语句中的名字,如果我们给对应表声明了别名的话,这里填的应该是别名 //后面应该是主表在SQL中的名字,有别名用别名,然后.后面接实体中,Join的模型的变量的名字 //例如AccountRelModel中我们声明AccountModel Join的变量名为account //因此这里填的是account_role_rel.account q.addJoin("account", "account_role_rel.account"); //同上 q.addJoin("role", "account_role_rel.role"); //返回的内容List<Object[AccountRelModel, AccountModel, RoleModel]>,顺序根据上面addEntity、addJoin的顺序产生对应的Object[]内用的顺序 return (List<Object[]>) q.list(); } } |