在实际的项目中,很多时候需要很复杂的查询,而JPQL有些功能是不支持的,Criteria的写法又过于复杂了。
用原生sql的方式进行查询会省很多事(缺点是和具体使用的数据库高度耦合了),但是使用JPA的createnativeQuery查询出来的却是一个Object对象,需要我们自己做一些封装的操作。
//查询语句,本地sql
String sql = "SELECT telephone, password FROM user where id = 1";
//查询
Object result = ssoEntityManager.createNativeQuery(sql)
.getSingleResult();
//将对象转换为数据
Object[] params = (Object[]) result;
//分别封装各个参数
UserDO userDO = new UserDO();
userDO.setTelephone(params[0].toString());
userDO.setPassword(params[1].toString());
如果是查询ResultList,则循环封装
这样的做法很麻烦,而且容易出错。其实JPA已经提供了对应的参数封装方法。
语法如下
query.unwrap(SQLQuery.class)
.setResultTransformer(
Transformers.aliasToBean(要转换的类)
)
.list();//根据实际情况调用不同的方法,list--》获取一个集合
完整的Demo
public class UserDO {
public UserDO () {}
private String telephone;
private String password;
//Setter,Getter
}
String sql = "SELECT telephone, password FROM user";
Query query = ssoEntityManager.createNativeQuery(sql);
List<UserDO> list = query.unwrap(SQLQuery.class)
.setResultTransformer(Transformers.aliasToBean(UserDO.class))
.list();
要注意:sql中的查询字段要和DO类中的属性相对应,如果有别名,那么别名要和属性对应
原生SQL不支持SetParameter方法,不能使用?0,:param等占位符,否则会报一个奇葩的错。
类中的属性仅支持基本类型、包装类型和String类型。枚举、其它类都是不支持的。(关于这点可以使用取巧用Set方法做转换。例子如下:)
class User{
private Gender sex;//性别的枚举,
public void setSex(String sex) {
this.sex = Gender.valueOf(sex);
}
}