摘自网上的一段解决办法。
原文: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.总结
由于我水平实在有限(大菜鸟一个啦),表达能力也不是很好,所以说了这么多也可能还没说明白,没说透彻。不过我觉的对大家有用的一个结论就是,无论什么操作,都放在事务里提交,这样是最省事,也是最保险的。
分享到:
相关推荐
在开发Java Web应用程序时,经常会遇到数据库操作中的字符编码问题,特别是当使用Hibernate框架与MySQL数据库结合时。本文将深入探讨“hibernate+mysql乱码问题”的原因、解决方案以及如何预防这类问题。 首先,...
通过测试,你可以确保代码能正确地插入、更新和查询数据。 这个实例旨在帮助初学者理解如何整合Hibernate3和MySQL,实现Java应用中的数据持久化。通过学习和实践,你将对这两个技术有更深入的理解,并能够将它们...
在Java开发中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用...在实际开发中,还需要理解并正确配置Hibernate的配置文件以及JDBC连接参数,以便高效地使用这两个工具。
在这个“使用Mysql+Maven+Hibernate的一对一,一对多的CURD小案例”中,我们将探讨如何在Java Web开发中结合这三个关键技术实现数据的创建(Create)、读取(Read)、更新(Update)和删除(Delete)操作。MySQL是一...
总的来说,如果你在使用Hibernate JPA时遇到了插入数据后自动执行`select last_insert_id()`的问题,检查`hibernate.temp.use_jdbc_metadata_defaults`的配置是一个有效的解决途径。但同时,也要确保这一改动不会...
在这个项目中,MySQL将作为数据存储的后端,存储由Hibernate操作的数据。 文件名称列表中的几个文件反映了Web应用的基本结构: 1. **listUser.jsp**:这是一个JSP(JavaServer Pages)文件,用于显示用户列表。它...
压缩包中的"sql.zip"文件可能包含了初始化数据库所需的SQL脚本,用于创建表结构、插入初始数据等。这些脚本可以快速设置项目运行环境,确保数据库的正确配置。 九、BYSJ(可能为项目源代码或其他文档) "BYSJ"文件...
### MySQL插入数据中文报错问题及解决方法 #### 背景介绍 在使用MySQL数据库进行数据管理的过程中,经常会遇到中文字符的存储需求。然而,在实际操作中可能会遇到中文字符无法正常插入数据库的问题,通常表现为错误...
在本项目中,Hibernate可能是用来进行数据持久化操作,如插入、更新、删除和查询信息。 3. **MySQL数据库**:MySQL是一款开源的关系型数据库管理系统,被广泛应用于Web应用。在这个系统中,MySQL存储所有的信息发布...
在“SSH2 jar包整合hibernate 3 mysql”这个主题中,我们将深入探讨如何将这些组件与MySQL数据库进行集成,以及在项目中使用必要的jar包。 首先,SSH2中的Struts2负责处理用户请求并提供视图层的展示,它的核心功能...
例如,要将数据插入到MySQL数据库,我们可以创建一个DAO类,如`Insert`,并利用Hibernate提供的Session接口进行数据操作。在`Insert`类中,我们可以创建一个方法,如`saveStudent(Student student)`,该方法会调用`...
10. **mysql-connector-java.jar**:这个JAR是MySQL的Java驱动程序,使得Hibernate能够连接到MySQL数据库进行数据操作。如果你使用其他数据库,比如Oracle或PostgreSQL,你需要对应的数据库驱动JAR。 在实际开发中...
* 数据类型自动转换:Hibernate 可以自动将 Java 对象转换为关系数据库中的数据类型,从而使得数据可以被正确地存储和读取。 * 支持多种数据库:Hibernate 支持多种关系数据库,包括 Oracle、MySQL、SQL Server 等。...
在这个例子中,Hibernate作为数据持久层,将业务对象与MySQL数据库中的表进行映射,通过HQL(Hibernate Query Language)或SQL实现数据查询、插入、更新和删除等操作。这使得开发者可以避免直接编写大量的JDBC代码,...
通过上述步骤,可以有效地解决Hibernate在插入数据到MySQL数据库时出现的中文乱码问题。值得注意的是,字符集的配置需要在整个应用链路中保持一致,包括数据库、连接池、Hibernate框架以及前端页面。此外,还可以...
4. **mysql-connector-java-5.0.5-bin.jar**:这是MySQL的JDBC驱动,用于连接MySQL数据库,使得Hibernate能够与MySQL进行通信并执行SQL语句。 5. **antlr-2.7.6.jar**:ANTLR是一个强大的解析器生成器,用于读取、...
对于学生信息管理系统,JUnit可以帮助开发者验证数据的增删改查功能是否正常,例如检查插入学生信息后,数据库中的记录是否准确无误。 这四个组件共同构建的学生信息管理系统,具有以下特点: - 使用Hibernate进行...
5. **数据插入**:通过PreparedStatement对象执行SQL语句,将处理后的数据插入MySQL数据库。PreparedStatement可以防止SQL注入,并且支持参数化查询。 6. **错误处理**:在整个过程中,应有适当的错误处理机制,...
Hibernate会在插入记录时自动获取数据库生成的主键值。这种方法简单且高效,但不跨数据库,因为不是所有数据库都支持自动增长。 6. **sequence**: sequence策略适用于支持序列的数据库,如PostgreSQL和Oracle。...
开发者可能使用了SQL语句来创建表、插入数据、执行查询和更新操作。 项目可能包含以下组成部分: 1. **前端页面**:HTML文件,使用CSS进行美化,展示书籍列表、搜索结果、用户登录/注册、购物车、订单等页面。 2. *...