`
comeonbabye
  • 浏览: 442105 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hibernate MySQL 无法正确插入数据

阅读更多

摘自网上的一段解决办法。

原文:http://blog.163.com/me_wxx/blog/static/13519139120105152638477/

 

下面是插入数据部分的程序:

public static void main(String[] args) {
  // TODO Auto-generated method stub
  User myuser= new User();
  myuser.setName("new name2");
  System.out.print("33333");
  myuser.setPassword("33333");
  UserDAO dao = new UserDAO();
  Transaction tran=dao.getSession().beginTransaction();
  
  dao.save(myuser);
 }
改正方法:

程序错误,将程序改为:

public static void main(String[] args) {
  // TODO Auto-generated method stub
  User myuser= new User();
  myuser.setName("new name3");
  System.out.print("33333");
  myuser.setPassword("33333");
  UserDAO dao = new UserDAO();
  Transaction tran=dao.getSession().beginTransaction();
  tran.begin();
  dao.save(myuser);
  tran.commit();
 }

关于此类问题,我在网上看到了一些其他解法,虽然我没有用上,但仍然给我一些启发,现将其他解法分享如下:

http://blog.csdn.net/teabook00/archive/2010/05/09/5571848.aspx

1.背景      

      之前从没用过hibernate,因此在网上搜了一下hibernate快速入门方面的信息,最后我按照《Myeclipse Hibernate 快速入门 中文版》(CSDN,百度文库都有)一文开始了我的hibernate之旅(为项目做技术准备)。

      下面是在学习使用时用到的三个开发工具(Myeclipse , Mysql , SQL-Front)及其版本说明:

      Myeclipse版本为6.5(没用最新的Myeclipse8.5,这是由于之前组里的项目都是在Myeclipse6.5中开发的,并且本项目是与 其它人合作完成的,为了防止可能由于开发环境的不一致而引起的问题,我们统一使用Myeclipse6.5,所以我就在Myeclipse6.5环境下学 习使用hibernate了)。

      Mysql使用的是5.1版本。Mysql安装完后,需要手动进行配置,其中有一项是“please select the database usage”,我在这里选择的是“Muitifunctional Database”(如下图所示)。这里其实选则的是使用何种类型的数据库(InnoDB还是MyISAM),如果选第三个,就不能用InnoDB类型的 数据库了,这个在每一个选项的说明中可以看到。

 

      为了方便mysql的使用,又安装了图形化界面的SQL-Front,版本是5.1。

2.遇到的问题

       我用SQL-Front在数据库中建了一简单的表用于学习,等同的SQL语句如下:

“author”表有两个字段,一个是主键“Id”,一个是“name”。需要说明的是SQL-Front在建表的时候默认数据库类型为InnoDB。

      针对“author”表,按照《Myeclipse Hibernate 快速入门 中文版》一文的说明操作完成后,写了一段简单的测试代码:

即插如一条name字段为“author”的数据,但是发现执行完后数据根本就没有插入到数据库中。后来在网上搜了一下,有人给出了解决办法,即使用事务来解决,修改后的代码如下:

数 据插入的问题是解决了,但是发现插入数据后,Id已经在插入前自动增加了(不是从1开始了),也就是说之前的测试虽然数据看似没有插入数据库,但是实际效 果却跟插入了数据库一样(要不然Id不会自动增加),这又是为什么?在网上搜了一下,结合自己的理解,我分析了一下原因。

 

3.原因

       上述问题的原因的本质我认为在于使用的数据库类型。

       我使用的数据库类型是“InnoDB”,这是一个支持事务的数据库类型,这种数据库你无论什么操作,最后如果你不“commit”的话,等于啥也没干(这 其中的道理在网上搜一下对数据库中事务的简单介绍应该不难理解)。虽然通过save方法可以将sql语句发送到数据库让其执行(备注:并不是所有的 save方法都会将sql语句发送到数据库,当主键生成策略为native的时候会发送到数据库,比如“author”的主键Id,其生成策略就为 native,不过可以通过dao.getSession().flush() 强行将sql语句发送到数据库。这些我 也只是知道一点皮毛,有时间还需要深入了解),数据库也确实执行了(分配了Id,并且将Id自动加1),但是这个执行的结果只是临时的,如果不 “commit”的话,随着会话session的结束(即上述代码中dao.getSession().close()语句),这个临时的执行结果也就没 了,直接的体现就是数据没有最终插入数据库。

       通过SQL-Front可以很好的观察到这一过程(针对未引入事务的那段代码),首先在dao.getSession().Close() 处 设置断点,然后用SQL-Front打开这个表,并设置SQL-Front与mysql的会话隔离级别为(Read Uncommitted,默认的级别为Repeatable Read,这个网上也有很多介绍的,也不多说了),然后执行测试代码,执行到断点处后,也即刚刚执行完dao.save(author) 而还没有关闭本次会话,通过SQL-Front会发现,这个数据插入到了表中(当然是“临时”插入数据,如果会话隔离级别不是Read Uncommitted的话是看不到这条插入的数据的),继续执行dao.getSession().close() 后,通过SQL-Front刷新“author”表中的数据,会发现刚刚插入的那条数据又消失了。

       不过这其中有一个比较特殊的地方,那就是Id这个自段了。这个字段是“author”表的主键,并且它的值是数据库自己产生的,在插入数据的时候不需要指 定这个字段的值。这个字段的特殊之处在于你在插入数据的时候,无论最后是否“commit”,这个字段的值都会自动加1供下一次插入数据时使用,不会说由 于本次会话没有“commit”,而在会话结束时自动减1恢复到原来的值。

       这一点我觉得应该是出于并发的考虑(没有查阅相关资料,只是提出我自己的猜测)。假设有三个会话A和B,都要向“author”表中插入数据(假设表中没 有数据,Id从1开始),A首先调用了save方法,数据库为A插入的数据分配的Id是1,然后“author”表将Id自动加1并保存,在A未 “commit”之前,B也调用了save方法,自然数据库为B插入的数据分配的Id是2(不会是1,如果是1,A和B将要提交的数据主键Id值就冲突 了,会造成A和B谁后“commit”数据谁失败,数据库就无法并发了),“author”表将Id字段再次加1后保存(此时为下一组数据使用的Id值为 3),假设B首先“commit”了数据,即“author”表中有了Id字段值为2的数据,而A最终没有“commit”数据,如果此时 “author”表的字段自动减1,可以看到,下一次数据插入分配的Id字段值就会是2,和现有的数据发成了主键冲突。因此,对于“author”表中 Id这个字段,无论某个插入操作是否最终“commit”,只要调用了save方法,Id字段就会自加1。这也能解释之前遇到的那个问题,即数据没有插 入,Id字段却自动增加了。

 

4.解决方法

     总共有两种解决方法:

      第一种 : 可以考虑使用“MyISAM”类型的数据库,这种类型的数据库不支持事务,因此在调用save方法的时候(注意,如果主键生成策略不是native的,必须在save后调用dao.getSession().flush() 方 法,即强行将sql语句发送到数据库,否则一样没有插入数据),数据就已经最终插入到数据库里了(注意,这是最终结果,不是临时结果,这和使用 “InnoDB”类型数据库时“commit”的效果是一样的)。当然了,直接使用事务机制(就像上面那段修改后的代码一样)也是可以的 (“MyISAM”类型的数据库虽然不支持事务,但是并不代表不能用hibernate里的事务机制,这两个概念还不太一样。当主键生成策略不是 native的时候,使用事务机制还省的调用dao.getSession().flush() 方法了)。mysql 支持“MyISAM”类型的数据库,可以在SQL-Front中直接将“InnoDB”类型的数据库转为“MyISAM”类型的数据库(建议这么做的时候 小心,因为看到网上有人说这么做可能会产生问题,不过我转换的时候倒是没碰到什么问题,也可能是我的“author”表简单的缘故),也可在建表的时候直 接指定类型为“MyISAM”。关于“MyISAM”类型的数据库的更多信息(比如相对于“InnoDB”类型数据库有什么优缺点)网上也有很多介绍,就 不在这里罗嗦了。

     第二种: 还是使用“InnoDB”类型的数据库。这时可以通过两种途径解决:一是像上面那个修改后的代码一样,加入事务机制,这是最保险的(也推荐使用);第二个途径就是在hibernate的配置文件中,加入自动提交的属性,如下图所示:

这个属性的作用是,一旦调用了save方法(和第一种解决方法一样,如果主键生成策略不是native的,必须在save后调用dao.getSession().flush() 方法),hibernate会自动帮你“commit”,在代码里不需要自己写关于事务的那些代码(例如commit调用)。这么做的缺点网上也有很多说明,也不在这里多说了。

 

5.总结

      由于我水平实在有限(大菜鸟一个啦),表达能力也不是很好,所以说了这么多也可能还没说明白,没说透彻。不过我觉的对大家有用的一个结论就是,无论什么操作,都放在事务里提交,这样是最省事,也是最保险的。

分享到:
评论

相关推荐

    hibernate+mysql乱码问题

    在开发Java Web应用程序时,经常会遇到数据库操作中的字符编码问题,特别是当使用Hibernate框架与MySQL数据库结合时。本文将深入探讨“hibernate+mysql乱码问题”的原因、解决方案以及如何预防这类问题。 首先,...

    hibernate3+mysql简单学习实例.rar

    通过测试,你可以确保代码能正确地插入、更新和查询数据。 这个实例旨在帮助初学者理解如何整合Hibernate3和MySQL,实现Java应用中的数据持久化。通过学习和实践,你将对这两个技术有更深入的理解,并能够将它们...

    Hibernate中连接MySql所需的jar包

    在Java开发中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用...在实际开发中,还需要理解并正确配置Hibernate的配置文件以及JDBC连接参数,以便高效地使用这两个工具。

    使用Mysql+Maven+Hibernate的一对一,一对多的CURD小案例

    在这个“使用Mysql+Maven+Hibernate的一对一,一对多的CURD小案例”中,我们将探讨如何在Java Web开发中结合这三个关键技术实现数据的创建(Create)、读取(Read)、更新(Update)和删除(Delete)操作。MySQL是一...

    解决Hibernate JPA中insert插入数据后自动执行select last_insert_id()

    总的来说,如果你在使用Hibernate JPA时遇到了插入数据后自动执行`select last_insert_id()`的问题,检查`hibernate.temp.use_jdbc_metadata_defaults`的配置是一个有效的解决途径。但同时,也要确保这一改动不会...

    Maven+Hibernate+mysql增删改查

    在这个项目中,MySQL将作为数据存储的后端,存储由Hibernate操作的数据。 文件名称列表中的几个文件反映了Web应用的基本结构: 1. **listUser.jsp**:这是一个JSP(JavaServer Pages)文件,用于显示用户列表。它...

    用hibernate和mysql实现的airline

    压缩包中的"sql.zip"文件可能包含了初始化数据库所需的SQL脚本,用于创建表结构、插入初始数据等。这些脚本可以快速设置项目运行环境,确保数据库的正确配置。 九、BYSJ(可能为项目源代码或其他文档) "BYSJ"文件...

    mysql插入数据中文报错问题,最全解决方式

    ### MySQL插入数据中文报错问题及解决方法 #### 背景介绍 在使用MySQL数据库进行数据管理的过程中,经常会遇到中文字符的存储需求。然而,在实际操作中可能会遇到中文字符无法正常插入数据库的问题,通常表现为错误...

    spring+hibernate+mysql的信息发布系统源码

    在本项目中,Hibernate可能是用来进行数据持久化操作,如插入、更新、删除和查询信息。 3. **MySQL数据库**:MySQL是一款开源的关系型数据库管理系统,被广泛应用于Web应用。在这个系统中,MySQL存储所有的信息发布...

    SSH2 jar包整合hibernate 3 mysql

    在“SSH2 jar包整合hibernate 3 mysql”这个主题中,我们将深入探讨如何将这些组件与MySQL数据库进行集成,以及在项目中使用必要的jar包。 首先,SSH2中的Struts2负责处理用户请求并提供视图层的展示,它的核心功能...

    Hibernate_ORM步骤详解

    例如,要将数据插入到MySQL数据库,我们可以创建一个DAO类,如`Insert`,并利用Hibernate提供的Session接口进行数据操作。在`Insert`类中,我们可以创建一个方法,如`saveStudent(Student student)`,该方法会调用`...

    hibernate需要的10个jar

    10. **mysql-connector-java.jar**:这个JAR是MySQL的Java驱动程序,使得Hibernate能够连接到MySQL数据库进行数据操作。如果你使用其他数据库,比如Oracle或PostgreSQL,你需要对应的数据库驱动JAR。 在实际开发中...

    Hibernate使用指南

    * 数据类型自动转换:Hibernate 可以自动将 Java 对象转换为关系数据库中的数据类型,从而使得数据可以被正确地存储和读取。 * 支持多种数据库:Hibernate 支持多种关系数据库,包括 Oracle、MySQL、SQL Server 等。...

    网上书店(struts2+hibernate3.2+Mysql)

    在这个例子中,Hibernate作为数据持久层,将业务对象与MySQL数据库中的表进行映射,通过HQL(Hibernate Query Language)或SQL实现数据查询、插入、更新和删除等操作。这使得开发者可以避免直接编写大量的JDBC代码,...

    hibernate插入数据库乱码的解决方式

    通过上述步骤,可以有效地解决Hibernate在插入数据到MySQL数据库时出现的中文乱码问题。值得注意的是,字符集的配置需要在整个应用链路中保持一致,包括数据库、连接池、Hibernate框架以及前端页面。此外,还可以...

    hibernate框架必备jar包

    4. **mysql-connector-java-5.0.5-bin.jar**:这是MySQL的JDBC驱动,用于连接MySQL数据库,使得Hibernate能够与MySQL进行通信并执行SQL语句。 5. **antlr-2.7.6.jar**:ANTLR是一个强大的解析器生成器,用于读取、...

    hibernate、struts、mysql_jdbc、junit

    对于学生信息管理系统,JUnit可以帮助开发者验证数据的增删改查功能是否正常,例如检查插入学生信息后,数据库中的记录是否准确无误。 这四个组件共同构建的学生信息管理系统,具有以下特点: - 使用Hibernate进行...

    excel数据导入mysql

    5. **数据插入**:通过PreparedStatement对象执行SQL语句,将处理后的数据插入MySQL数据库。PreparedStatement可以防止SQL注入,并且支持参数化查询。 6. **错误处理**:在整个过程中,应有适当的错误处理机制,...

    hibernate的主键生成策略

    Hibernate会在插入记录时自动获取数据库生成的主键值。这种方法简单且高效,但不跨数据库,因为不是所有数据库都支持自动增长。 6. **sequence**: sequence策略适用于支持序列的数据库,如PostgreSQL和Oracle。...

    网上书店(struts+hibernate+css+mysql)130223.zip

    开发者可能使用了SQL语句来创建表、插入数据、执行查询和更新操作。 项目可能包含以下组成部分: 1. **前端页面**:HTML文件,使用CSS进行美化,展示书籍列表、搜索结果、用户登录/注册、购物车、订单等页面。 2. *...

Global site tag (gtag.js) - Google Analytics