开发万步网后台管理系统的用户详情和改名功能时用到了hibernate 其中有多出异常都是由hibernate引起的,下面我就把我遇到的
问题和解决方法一一列出供大家参考。。。
1. hql书写问题
1.1 当我们写hql的时候如果用?占位符方式传参切记如果是字符串的千万不要再hql中对?左右加' ' 我们只写? 下面有那个query
.setString(); 来赋值就行了。
1.2 用hql更新或插入的时候不要用”++“来拼接中文参数那样是不会起到作用的而要用:参数名称 或 ? 这两种方式来赋值英文的参数是可以的 当然这只是针对于hibernate3来讲的 听说 >=hibernate3.1的已经支持用“++”方式操作中文了。
1.3. 用hql执行update 时候不能再为表起别名,在对涉及到复合主键的表update时候也不能用别名.id.属性方式操作属性了。
错误代码:hql="update WanbuRankStar w set w.id.username=:username where w.id.username=:beforename";
正确代码:hql="update WanbuRankStar set username=:username where username=:beforename";
1.4 当用hql进行多表联查时候记住hibernate的hql是不支持inner join on 或 left join on 的 只要带on就不对不管是内,左,右,交叉,全 什 么形式的连接所以我们只能用sql来进行了。
2. 投影查询问题
/**
* 根据参数,hql语句查询
* @param hql
* @param params
* @return
*/
public List getList(String hql, String[] params) {
Session session = getSession();
Query query = null;
try {
query = session.createQuery(hql);
if(params!=null)
{
for (int i=0;i<params.length;i++) {
query.setString(i, params[i]);
}
}
List list=query.list();
if(list!=null &&list.size()!=0){
return list;
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (session != null && session.isOpen()) {
closeSession();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
1.投影查询如果只查询一个字段query.ist() 是返回list<.object> 列表的而每一个object对象里面放的就是改字段的实际类型需要我们转换一下
来用 用例代码:
public List<String> getUsername() {
String hql="select u.username from PreUcenterMembers u";
List<String> ulist=super.getList(hql, null); //getList();方法返回一个包含object对象的 List<object >列表。
if(ulist !=null){
return ulist;
}
return null;
}
//结果输出
public static void main(String[] args) throws UnsupportedEncodingException {
IUserManageDao um=new UserManageImpl();
List<String> s=um.getUsername();
System.out.println(s); //输出 [得实陈其, 得实陈庆义, 得实陈尚岩, 得实陈世华, 得实陈薇薇] String 类型的数组。
}
2. 投影查询查询多个字段(无论是一个表中多个字段还是多个表中的不同字段 有或者是不同库中不同表的一些字段 都适用 我们只需将
涉及到的表和类 映射好就行了)
2.1 当查询多个字段的时候query.list() 返回list<object [] > 列表而每一个object[]就是查询的这几个字段的集合并且也类型也对应着实际字段的类型 我们用的时候可以遍历list<object []> 将其元素封装成我们的实体列表当然这个实体类中的属性类型应该和查询返回字段类型一一对应。 用例代码:
public UserDetailData getUserInfo(String uname) {
String hql="select p.address,u.email,p.gender,p.mobile,j.nickname,p.realname,FROM_UNIXTIME(u.regdate),u.regip,u.username,p.resideprovince,p.residecity,p.residecommunity,p.residesuite,p.residedist " +
" from PreUcenterMembers u"
+" ,PreCommonMemberProfile p "
+" ,JishigouMembers j where u.uid=j.uid and u.uid=p.uid and u.username=?";
List<Object []> uinfo=super.getList(hql,new String[]{uname});
UserDetailData ud=null;
if(uinfo !=null){
for(Object [] u : uinfo){
ud=new UserDetailData();
ud.setAddress((String)u[0]);
ud.setEmail((String)u[1]);
ud.setGender((Byte)u[2]);
ud.setMobile((String)u[3]);
ud.setNickname((String)u[4]);
ud.setRealname((String)u[5]);
ud.setRegdate(u[6].toString());
ud.setRegip((String)u[7]);
ud.setUsername((String)u[8]);
ud.setResideprovince((String)u[9]);
ud.setResidecity(u[10].toString());
ud.setResidedist(u[11].toString());
ud.setResidecommunity(u[12].toString());
ud.setResidesuite(u[13].toString());
}
return ud;
}
return null;
}
public class UserDetailData {
// Fields 这些类型要与查询后返回的字段类型一致 查询返回字段类型并不是数据库中的字段或你映射好的属性类型而是实实在在返回的类型 例: regdate 在PreUcenterMembers 中为Interger 而此处要为timestamp因为当查询regdate时 FROM_UNIXTIME(u.regdate) 返回的是timestamp 但因为 ud.setRegdate(u[6].toString()); 做了转换所以该类regdate在此处为String,当然因为此查询返回的list<object>所以可以这么写,要是你想用new 方式来实现则该类属性是必须与数据库字段类型对应的。
private String address;
private String email;
private Byte gender;
private String mobile;
private String nickname;
private String realname;
private String regdate;
private String regip;
private String username;
private String resideprovince;
private String residecity;
private String residedist;
private String residecommunity;
private String residesuite;
public UserDetailData(String address, String email, Byte gender,
String mobile, String nickname, String realname, String regdate,
String regip, String username) {
super();
this.address = address;
this.email = email;
this.gender = gender;
this.mobile = mobile;
this.nickname = nickname;
this.realname = realname;
this.regdate = regdate;
this.regip = regip;
this.username = username;
}
//此处省略get/set 方法
}
}
上面这种形式完全可以解决对多表联查的投影查询返回结果封装问题而且对要封装返回结果的实体类属性类型没什么严格限制我们可以根据我们要在页面上展示的数据形式来决定他的类型相对new方式比较灵活,所以推荐使用。
2.2 一种更简单的方式我们可以事先建立好一个类用来封装查询结果,这个类中的属性和数据库的字段类型一致并且有无参构造和对应查询字段的构造,然后采用select new(放入字段对应的属性)from 类名 方式为其实例化,这个query.list()返回的就是list<这个类> 列表,用例代码:
public UserDetailData getUserInfo(String uname) {
/*
* private String resideprovince;
private String residecity;
private String residedist;
private String residecommunity;
private String residesuite;
*/
String hql="select new UserDetailData(p.address,u.email,p.gender,p.mobile,j.nickname, p.realname,u.regdate,u.regip,u.username,p.resideprovince,p.residecity,p.residedist,p.residecommunity,p.residesuite) " +
" from PreUcenterMembers u"
+" ,PreCommonMemberProfile p "
+" ,JishigouMembers j where u.uid=j.uid and u.uid=p.uid and u.username=?";
List<UserDetailData> u=super.getList(hql, new String [] {uname});
if(u!=null ){
return u.get(0);
}
return null;
}
public class UserDetailData {
// Fields 此处regdate 必须为Integer 也就是要和数据库表的字段类型一致了。。。
private String address;
private String email;
private Byte gender;
private String mobile;
private String nickname;
private String realname;
private Integer regdate;
private String regip;
private String username;
private String resideprovince;
private String residecity;
private String residedist;
private String residecommunity;
private String residesuite;
public UserDetailData(String address, String email, Byte gender,
String mobile, String nickname, String realname, String regdate,
String regip, String username) {
super();
this.address = address;
this.email = email;
this.gender = gender;
this.mobile = mobile;
this.nickname = nickname;
this.realname = realname;
this.regdate = regdate;
this.regip = regip;
this.username = username;
}
//此处省略get/set 方法
}
}
这里说明一下吧,我在使用这种方式的时候出现过问题 1.org.hibernate.hql.ast.QuerySyntaxError: Unable to locate class [UserDetailData]
2.在涉及到复合主键的类时也存在问题。
分享到:
相关推荐
Criteria API 提供了一种更加面向对象的查询方式,无需书写字符串HQL,通过构建查询条件对象,可以方便地完成查询任务。 六、 Criteria API的常用方法 - createCriteria():创建Criteria对象,指定要查询的实体类。...
- **投影查询**:仅选择部分字段作为查询结果返回,提高查询效率。 #### Hibernate查询语言(HQL) - **概念**:Hibernate Query Language,一种面向对象的查询语言,类似于SQL但更加面向对象。 - **特点**: - ...
少儿编程scratch项目源代码文件案例素材-直升机飞行.zip
wanjunshe_Python-Tensorflow_12888_1745868924470
健康监测_Android开发_BLE蓝牙通信_心率数据采集与存储_基于小米手环2的实时心率监测应用_支持后台长时间运行的心率记录工具_可导出SQLite数据库的心率数据分析系统_适
少儿编程scratch项目源代码文件案例素材-种花模拟器.zip
嵌入式系统开发_FreeRTOS实时操作系统_STM32F103C8T6微控制器_OLED显示屏_DHT11温湿度传感器_多任务调度_多级菜单设计_万年历算法_电子闹钟功能_参数配
基于python实现的粒子群的VRP(车辆配送路径规划)问题建模求解+源码+项目文档+算法解析,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 算法设计的关键在于如何向表现较好的个体学习,标准粒子群算法引入惯性因子w、自我认知因子c1、社会认知因子c2分别作为自身、当代最优解和历史最优解的权重,指导粒子速度和位置的更新,这在求解函数极值问题时比较容易实现,而在VRP问题上,速度位置的更新则难以直接采用加权的方式进行,一个常见的方法是采用基于遗传算法交叉算子的混合型粒子群算法进行求解,这里采用顺序交叉算子,对惯性因子w、自我认知因子c1、社会认知因子c2则以w/(w+c1+c2),c1/(w+c1+c2),c2/(w+c1+c2)的概率接受粒子本身、当前最优解、全局最优解交叉的父代之一(即按概率选择其中一个作为父代,不加权)。 算法设计的关键在于如何向表现较好的个体学习,标准粒子群算法引入惯性因子w、自我认知因子c1、社会认知因子c2分别作为自身、当代最优解和历史最优解的权重,指导粒子速度和位置的更新,这在求解函数极值问题时比较容易实现,而在VRP问题上,速度位置的更新则难以直接采用加权的方式进行,一个常见的方法是采用基于遗传算法交叉算子的混合型粒子群算法进行求解,这里采用顺序交叉算子,对惯性因子w、自我认知因子c1、社会认知因子c2则以w/(w+c1+c2),c1/(w+c1+c2),c2/(w+c1+c2)的概率接受粒子本身、当前最优解、全局最优解交叉的父代之一(即按概率选择其中一个作为父代,不加权)。
scratch少儿编程逻辑思维游戏源码-猫猫粉碎.zip
scratch少儿编程逻辑思维游戏源码-蓝胡子.zip
scratch少儿编程逻辑思维游戏源码-美食大亨.zip
scratch少儿编程逻辑思维游戏源码-洛克人.zip
scratch少儿编程逻辑思维游戏源码-龙冲刺.zip
思幻个人引导页V2.2版本11月29日更新.zip
scratch少儿编程逻辑思维游戏源码-骑士风斩法.zip
移动应用开发_H5CSS3ionicng-cordovaMVVM模式_基于HTML5和CSS3技术实现多页面布局ionic指令数据绑定ui-route单页跳转调用手机
少儿编程scratch项目源代码文件案例素材-植物大战僵尸创造版 Ver. 1.0.3.zip
scratch少儿编程逻辑思维游戏源码-日落(2).zip
动态星空背景个人主页(带后台).zip
scratch少儿编程逻辑思维游戏源码-迷雾森林:诞生 3.2 起源觉醒.zip