日期:2014-05-16  浏览次数:21047 次

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”表的主键,并且它的值是数据库自己产生的,在插入数据的时候不需要指 定这个字段的值。这个字段的特殊之处在于你在插入数据的时候,