这篇博客来自我自己的博客,欢迎多点上来wishselfly's blog
在一些实际的开发环境中,我们查询一张表,可能需要关联到另外一张表的信息,不是那种已经存在于数据库表的字段中的数据,可能是需要统计的一些数据,例如我需要知道这个用户在系统下面到底有多少中角色,写成SQL可能是
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语句查询结果的代码如下:
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里面有很多基本类型:
还记得我们之前声明的用户和角色的关联表:
现在我们需要声明AccountRoleRelModel.java,我需要在里面Join上RoleModel和AccountModel的实体:
/**
* 用户与角色的关联表的实体
*/
@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加入对应实体的映射:
@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();
}
}