最近的一个项目,使用的是一个古老的开发脚手架平台JEECG,是的,从官网上可以看出这个脚手架是2013年的,现在他们官网主推的是JEECG BOOT,不过现在接手的这个项目是JEECG,项目中用到的持久层框架是Hibernate。由于基本上没用过Hibernate,所以在项目中踩了很多坑,出现问题,在网上找解决方案也非常少,针对最近遇到的一些问题,做个总结:

1,创建session的两种方式的不同

使用SessionFactory创建session的两种方式:使用openSession()这个方法或者getCurrentSession()方法,创建session,但是这两种是有很大差别的

使用openSession()创建的session是需要每次手工关闭session的,即调用session.close()方法。所以在使用@transactional注解的service层,调用dao层增删改查的时候,事务通常会不起作用,因为调用的时候,session已经关闭了,事务不能正常激活,

像这样的写法就不行的,例如下service层中,调用这个save方法,一调用session就关闭了,事务无法参与进去:

Repository("hotelPreOrderDao")
public class HotelPreOrderDaoImpl implements HotelPreOrderDao{private TmcHotelPreOrder tmcHotelPreOrder=new TmcHotelPreOrder();@AutowiredSessionFactory sessionFactory;@Overridepublic void save(TmcHotelPreOrder tmcHotelPreOrder) {Session session = sessionFactory.openSession();session.save(tmcHotelPreOrder);session.close();}@Overridepublic void update(TmcHotelPreOrder tmcHotelPreOrder) {Session session = sessionFactory.openSession();session.update(tmcHotelPreOrder);session.close();}}

这样写的话,在service层的方法中虽然加了@transactional注解,在service层的方法中调用HotelPreOrderDao.save()方法,事务是不起效的,会报错;

所以可以使用另外一种获取session的方法,这种可以在执行完事务后,自动关闭session,如下:

@Repository("hotelPreOrderDao")
public class HotelPreOrderDaoImpl implements HotelPreOrderDao{private TmcHotelPreOrder tmcHotelPreOrder=new TmcHotelPreOrder();@AutowiredSessionFactory sessionFactory;@Overridepublic void save(TmcHotelPreOrder tmcHotelPreOrder) {Session session = sessionFactory.getCurrentSession();session.save(tmcHotelPreOrder);}@Overridepublic void update(TmcHotelPreOrder tmcHotelPreOrder) {Session session = sessionFactory.getCurrentSession();session.update(tmcHotelPreOrder);}@Overridepublic void delete(Serializable id) {Session session = sessionFactory.getCurrentSession();session.delete(this.findById(id));}@Overridepublic TmcHotelPreOrder findById(Serializable id) {Session session = sessionFactory.getCurrentSession();return (TmcHotelPreOrder)session.get(tmcHotelPreOrder.getClass(),id);}/*** 通过hql查询* @param hql* @param paranms 条件参数值* @return 查询结果,多条数据*/@Overridepublic List<TmcHotelPreOrder> findByHQL(String hql, Object... paranms) {Session session = sessionFactory.getCurrentSession();Query query = session.createQuery(hql);for (int i=0;paranms!=null&&i<paranms.length;i++){query.setParameter(i,paranms);}return query.list();}
}

sessionFactory是在xml文件中配置的,所以可以直接注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="com.gbiac.hotelier.*"/><context:property-placeholder location="classpath:dbconfig.properties"/><!--配置c3p0--><!--配置c3p0--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="${jdbc.username.jeecg}"></property><property name="password" value="${jdbc.password.jeecg}"></property><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url.jeecg}"></property><property name="initialPoolSize" value="${jdbc.initPoolSize}"></property><property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property></bean><bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:hibernate.cfg.xml"/><property name="packagesToScan"><list><value>com.gbiac.hotelier.*</value></list></property></bean><bean name="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/><property name="dataSource" ref="dataSource"/></bean><!--配置注解驱动,使可以使用注解来管理事务--><tx:annotation-driven transaction-manager="transactionManager"/></beans>

同时还有一个hibernate的配置项需要注释掉,或者不配置:hibernate.cfg.xml文件

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><!--配置基本属性--><!--hibernate方言--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 在控制台显示执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 格式化sql语句,更易读 --><property name="hibernate.format_sql">true</property><!--生成数据表策略--><!--<property name="hibernate.hbm2ddl.auto">update</property>--><!-- 启用二级缓存 --><!--<property name="cache.use_second_level_cache">true</property>--><!--&lt;!&ndash; 设置二级缓存的实现类,即指定使用的插件 &ndash;&gt;--><!--<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>--><!--&lt;!&ndash; 启用查询缓存 &ndash;&gt;--><!--<property name="cache.use_query_cache">true</property>--><!--把session绑定到本地线程--><!--<property name="hibernate.current_session_context_class">thread</property>--></session-factory>
</hibernate-configuration>

将那个绑定本地线程的配置注释掉,或者删除这个配置项

这样就可以正常用@transactional注解来管理事务,同时session也不用手动去关闭了,getCurrentSession()会在事务提交后,自动关闭session。

service层加@transactional注解来管理事务

2,HQL写法与hibernate支持的原生sql写法的区别

今天本来是要用hql语句写更新语句,结果在建立执行语句时用错了方法

@Overridepublic Integer updateByHQL(String fcOrderCode,Integer orderStatus,String orderStatusMessage) {Session session=sessionFactory.getCurrentSession();
//        原生sql方式更新
//        String updateSql="update tmc_hotel_order set order_status= :order_status,order_status_message= :order_status_message where fc_order_code= :fc_order_code ";
//        int rowNum = session.createSQLQuery(updateSql).setInteger("order_status", orderStatus).setString("order_status_message", orderStatusMessage)
//                .setString("fc_order_code", fcOrderCode).executeUpdate();
//        HQL方式更新String hql="update TmcHotelOrder set orderStatus= :order_status,orderStatusMessage= :order_status_message,modifiedTime= :modified_time where fcOrderCode= :fc_order_code ";
//        保留日期和时间需要使用setTimeStamp方法,setDate截断time,SetTime会截断dateint rowNum = session.createQuery(hql).setInteger("order_status", orderStatus).setString("order_status_message", orderStatusMessage).setString("fc_order_code", fcOrderCode).setTimestamp("modified_time",new Date()).executeUpdate();return rowNum;}

我最初用的hql语句写的更新语句,表名和字段用的都是实体类的类名和属性名,因为在实体类中已经用JPA注解映射了实体类和数据表的对应关系,hql语句写的是正确的,但是比较坑的地方是下边这样:

 String hql="update TmcHotelOrder set orderStatus= :order_status,orderStatusMessage= :order_status_message,modifiedTime= :modified_time where fcOrderCode= :fc_order_code ";int rowNum = session.createSQLQuery(updateSql).setInteger("order_status", orderStatus).setString("order_status_message", orderStatusMessage).setString("fc_order_code", fcOrderCode).executeUpdate();

是的,我用错方法了,我用成了session.createSQLQuery()这个方法,但是这样用的话,是不对的,hibernate的update语句就变成了update TmcHotelOrder ...,但是根本不存在TmcHotelOrder 这个数据表,运行项目,也会报错,说TmcHotelOrder table not  exist;因为session.createSQLQuery()这个方法是执行原生SQL语句的,要使用这个方法,表名和字段名需要是真实的表名和字段名,而不应该是映射的实体类名和属性名。

所以后边改过来了,HQL的增删改查,需要使用session.createQuery(hql)这个方法。这样hibernate会自动根据映射关系,在执行update语句时,会自动更改成表名为tmc_hotel_order,属性名也会自动映射成真正的字段名,就和原生sql的增删改查是一样的啦。

实体类时这样的:

package com.gbiac.hotelier.entity;import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;/*** 酒店预订表*/
@Entity
@Table(name = "tmc_hotel_order")
public class TmcHotelOrder implements Serializable {private static final long serialVersionUID = 1L;/*** 主键id*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Integer id;/*** 酒店id*/@Column(name = "hotel_id")private Integer hotelId;/*** 房型id*/@Column(name = "room_id")private Integer roomId;/*** 价格计划id*/@Column(name = "rate_plan_id")private Integer ratePlanId;/*** 入住日期*/@DateTimeFormat(pattern = "yyyy-MM-dd")@Column(name = "check_in_date")private Date checkInDate;/*** 离店日期*/@DateTimeFormat(pattern = "yyyy-MM-dd")@Column(name = "check_out_date")private Date checkOutDate;/*** 预订间数*/@Column(name = "room_num")private Integer roomNum;/*** 房间状态 1:有房 2:待查 3:满房*/@Column(name = "room_status")private Integer roomStatus;/*** 床型*/@Column(name = "bed_type")private String bedType;/*** 总金额*/@Column(name = "total_amount")private Double totalAmount;/*** 合作商订单号*/@Column(name = "co_order_code")private String coOrderCode;/*** 泰坦云订单号*/@Column(name = "fc_order_code")private String fcOrderCode;/*** 预订结果 1-预订成功  2-预订失败 */@Column(name = "result", nullable = false)private Integer result;/*** 预订失败的原因*/@Column(name = "message")private String message;/*** 订单状态 1:新建  2:处理中 3:已确认 4:已取消*/@Column(name = "order_status", nullable = false)private Integer orderStatus;@Column(name = "order_status_message")private String orderStatusMessage;public String getOrderStatusMessage() {return orderStatusMessage;}public void setOrderStatusMessage(String orderStatusMessage) {this.orderStatusMessage = orderStatusMessage;}/*** 订单联系人*/@Column(name = "link_man", nullable = false)private String linkMan;/*** 联系人电话*/@Column(name = "link_phone", nullable = false)private String linkPhone;/*** 邮箱*/@Column(name = "email")private String email;/*** 到店时间(格式HH:mm)*/@Column(name = "arrive_time", nullable = false)private String arriveTime;/*** 最晚到店时间(格式HH:mm)*/@Column(name = "latest_arrive_time", nullable = false)private String latestArriveTime;/*** 供应商编码*/@Column(name = "supply_code", nullable = false)private String supplyCode;/*** 客户特殊要求*/@Column(name = "special_demand")private String specialDemand;/*** 订单创建时间*/@Column(name = "create_time")private Date createTime;/*** 订单修改时间*/@Column(name = "modified_time")private Date modifiedTime;/*** 操作者*/@Column(name = "operator")private String operator;/*** 备注字段*/@Column(name = "remark")private String remark;/*** 主键id*/public Integer getId() {return id;}/*** 主键id*/public void setId(Integer id) {this.id = id;}/*** 酒店id*/public Integer getHotelId() {return hotelId;}/*** 酒店id*/public void setHotelId(Integer hotelId) {this.hotelId = hotelId;}/*** 房型id*/public Integer getRoomId() {return roomId;}/*** 房型id*/public void setRoomId(Integer roomId) {this.roomId = roomId;}/*** 价格计划id*/public Integer getRatePlanId() {return ratePlanId;}/*** 价格计划id*/public void setRatePlanId(Integer ratePlanId) {this.ratePlanId = ratePlanId;}/*** 入住日期*/public Date getCheckInDate() {return checkInDate;}/*** 入住日期*/public void setCheckInDate(Date checkInDate) {this.checkInDate = checkInDate;}/*** 离店日期*/public Date getCheckOutDate() {return checkOutDate;}/*** 离店日期*/public void setCheckOutDate(Date checkOutDate) {this.checkOutDate = checkOutDate;}/*** 预订间数*/public Integer getRoomNum() {return roomNum;}/*** 预订间数*/public void setRoomNum(Integer roomNum) {this.roomNum = roomNum;}/*** 房间状态 1:有房 2:待查 3:满房*/public Integer getRoomStatus() {return roomStatus;}/*** 房间状态 1:有房 2:待查 3:满房*/public void setRoomStatus(Integer roomStatus) {this.roomStatus = roomStatus;}/*** 床型*/public String getBedType() {return bedType;}/*** 床型*/public void setBedType(String bedType) {this.bedType = bedType;}/*** 总金额*/public Double getTotalAmount() {return totalAmount;}/*** 总金额*/public void setTotalAmount(Double totalAmount) {this.totalAmount = totalAmount;}/*** 合作商订单号*/public String getCoOrderCode() {return coOrderCode;}/*** 合作商订单号*/public void setCoOrderCode(String coOrderCode) {this.coOrderCode = coOrderCode;}/*** 泰坦云订单号*/public String getFcOrderCode() {return fcOrderCode;}/*** 泰坦云订单号*/public void setFcOrderCode(String fcOrderCode) {this.fcOrderCode = fcOrderCode;}/*** 预订结果 1-预订成功  2-预订失败 */public Integer getResult() {return result;}/*** 预订结果 1-预订成功  2-预订失败 */public void setResult(Integer result) {this.result = result;}/*** 预订失败的原因*/public String getMessage() {return message;}/*** 预订失败的原因*/public void setMessage(String message) {this.message = message;}/*** 订单状态 1:新建  2:处理中 3:已确认 4:已取消*/public Integer getOrderStatus() {return orderStatus;}/*** 订单状态 1:新建  2:处理中 3:已确认 4:已取消*/public void setOrderStatus(Integer orderStatus) {this.orderStatus = orderStatus;}/*** 订单联系人*/public String getLinkMan() {return linkMan;}/*** 订单联系人*/public void setLinkMan(String linkMan) {this.linkMan = linkMan;}/*** 联系人电话*/public String getLinkPhone() {return linkPhone;}/*** 联系人电话*/public void setLinkPhone(String linkPhone) {this.linkPhone = linkPhone;}/*** 邮箱*/public String getEmail() {return email;}/*** 邮箱*/public void setEmail(String email) {this.email = email;}/*** 到店时间(格式HH:mm)*/public String getArriveTime() {return arriveTime;}/*** 到店时间(格式HH:mm)*/public void setArriveTime(String arriveTime) {this.arriveTime = arriveTime;}/*** 最晚到店时间(格式HH:mm)*/public String getLatestArriveTime() {return latestArriveTime;}/*** 最晚到店时间(格式HH:mm)*/public void setLatestArriveTime(String latestArriveTime) {this.latestArriveTime = latestArriveTime;}/*** 供应商编码*/public String getSupplyCode() {return supplyCode;}/*** 供应商编码*/public void setSupplyCode(String supplyCode) {this.supplyCode = supplyCode;}/*** 客户特殊要求*/public String getSpecialDemand() {return specialDemand;}/*** 客户特殊要求*/public void setSpecialDemand(String specialDemand) {this.specialDemand = specialDemand;}/*** 订单创建时间*/public Date getCreateTime() {return createTime;}/*** 订单创建时间*/public void setCreateTime(Date createTime) {this.createTime = createTime;}/*** 订单修改时间*/public Date getModifiedTime() {return modifiedTime;}/*** 订单修改时间*/public void setModifiedTime(Date modifiedTime) {this.modifiedTime = modifiedTime;}/*** 操作者*/public String getOperator() {return operator;}/*** 操作者*/public void setOperator(String operator) {this.operator = operator;}/*** 备注字段*/public String getRemark() {return remark;}/*** 备注字段*/public void setRemark(String remark) {this.remark = remark;}@Overridepublic String toString() {return "TmcHotelOrder{" +"id=" + id +", hotelId=" + hotelId +", roomId=" + roomId +", ratePlanId=" + ratePlanId +", checkInDate=" + checkInDate +", checkOutDate=" + checkOutDate +", roomNum=" + roomNum +", roomStatus=" + roomStatus +", bedType='" + bedType + '\'' +", totalAmount=" + totalAmount +", coOrderCode='" + coOrderCode + '\'' +", fcOrderCode='" + fcOrderCode + '\'' +", result=" + result +", message='" + message + '\'' +", orderStatus=" + orderStatus +", orderStatusMessage='" + orderStatusMessage + '\'' +", linkMan='" + linkMan + '\'' +", linkPhone='" + linkPhone + '\'' +", email='" + email + '\'' +", arriveTime='" + arriveTime + '\'' +", latestArriveTime='" + latestArriveTime + '\'' +", supplyCode='" + supplyCode + '\'' +", specialDemand='" + specialDemand + '\'' +", createTime=" + createTime +", modifiedTime=" + modifiedTime +", operator='" + operator + '\'' +", remark='" + remark + '\'' +'}';}
}

表字段是这样的:

控制台中,使用hql方式执行的更新,语句输出在控制台中是这样的:

 先暂时更新到这里。现在不早了,这个月先总结这些吧,最近很忙,写博客的时间很少!

Hibernate使用的一些细节注意事项相关推荐

  1. 网站外链发布的细节注意事项!

    在网站优化的过程中,我们都会使用外链来为网站增加流量和权重,但是发布外链并不是一件简单的事情,一定要注意发布外链时的细节和事项,才能确保网站外链发挥更多的作用.那么网站发布外链时都应注意哪些事项呢?下 ...

  2. 解决方案需求提升 安防工程细节化事项要了解

    安防监控系统是一门被人们日益重视的新兴专业,就目前发展看,安防系统工程应用普及越来越广,科技含量越来越高.几乎所有高新科技都可促进其发展,尤其是信息时代的来临,更为该专业发展提供契机.安防工程就是实现 ...

  3. 小白入门炒股票关键词解释及细节注意事项

    炒股关键词解释 文章目录 炒股关键词解释 名称解释 五档 委买手数 委卖手数 委比与委差 委比 委差 量比 成交额 换手(率) 外盘 内盘 市盈(率) PE 市净(率) 每股收益 净资本 ROE 总股 ...

  4. 网站SEO优化需要注意哪些细节事项?

    随着网站建设越来越火热,同样网站优化也得到了更多人们的关注,优化人员对网站的细节优化也难免会有疏忽的现象出现,就会给网站带来不好的影响,那么也就需要优化人员掌握更多的细节优化点,今天就带大家分享一下网 ...

  5. Hibernate开发和对象状态

    Hibernate开发和对象状态 Hibernate开发三种方式 1.由Domain object -> mapping->db.(官方推荐) 2.由DB开始,用工具生成mapping和D ...

  6. 浅析 Mybatis 与 Hibernate 的区别与用途

    有很长一段时间对mybatis是比较陌生的,只知道与Hibernate一样是个orm数据库框架.随着使用熟练度的增加,发现它与Hibernate区别是非常大的,应当结合不同的情况分析选用.结合至今为止 ...

  7. MyBatis与Hibernate比较

    MyBatis: 1.是一个sql语句映射的框架(工具). 2.注重pojo与sql之间的映射关系.不会为程序员在运行期自动生成sql 3.自动化程度低,手工映射sql灵活程度高 4.需要开发人员熟练 ...

  8. Hibernate4实战 之 第一部分 Hibernate入门

    第一部分:Hibernate入门 Hibernate是什么 Hibernate是一个轻量级的ORMapping框架 ORMapping原理(Object Relational Mapping) ORM ...

  9. mybatis和hibernate的对比总结

    mybatis和hibernate 第一步, 首先让我们对mybatis和hibernate对比了解下 1. Hibernate :Hibernate 是当前非常流行的ORM框架,对数据库结构提供了较 ...

最新文章

  1. 模板—主席树(待修改)
  2. LoadRunner中对图表的分析说明
  3. Android 圆形/圆角图片的方法
  4. Spartacus同SAP Commerce Cloud交互的示意图
  5. 求二叉树中结点个数代码java_求二叉树中第K层结点的个数
  6. LeetCode:Remove Nth Node From End of List 移除链表倒第n项
  7. linux桌面_使用 KDE Plasma 定制 Linux 桌面 | Linux 中国
  8. 周三直播预告丨openGauss和MogDB的优化分享
  9. mysql 字符串截取_mysql数据库13种常用函数方法总结
  10. SQLServer查询所有表所有字段包含xx的信息
  11. mysql 事件调度器_【MySQL】事件调度器 (Event Scheduler)
  12. jqgrid ajax reload,于jqgrid.trigger('reloadGrid')方法不能重新加载页面的问题
  13. python基础语法手册-Python学习手册(第4版)pdf
  14. java解析字符串_java 拼接字符和解析字符串
  15. Fortran入门教程(八)——子例程及函数
  16. 计算机音乐怎么调音速,音频实现变声?学会使用Studio One改变音速
  17. <C++ 初阶> C++入门
  18. 目标检测中anchor的概念
  19. 【数据挖掘】关联规则的术语及定义
  20. outlook电子邮件解析_在Outlook中按会话对电子邮件进行排序

热门文章

  1. JSF,Servlet和JSP有什么区别?
  2. C语言小程序显示心形,如何用vc6.0编出来一个心形
  3. win11网络无法连接怎么办 Windows11连不上网的解决方法
  4. web网络图片查看器Android
  5. python中关于命名的例子_Python()-类命名空间和对象/实例命名空间
  6. Car-like Robot运动模型及应用分析
  7. java引用复制_Java中引用的浅复制和深复制
  8. python不调包实现sobel_python利用百度云接口实现车牌识别的示例
  9. vue项目H5 跳转微信小程序
  10. Qt之问题: Unknown module(s) in QT: multimedia