这是我第一天学习hibernate遇到的问题,纠结了一天终于解决了。
项目功能很简单,就是保存一条数据到数据库。我完全照着尚硅谷佟刚老师的hibernate4.0的视频写的,结果运行一直出现找不到表的问题。
先看JUnit的Failure Trace报的错
org.hibernate.exception.SQLGrammarException: could not execute statement
at ......此处省略
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.news_table' doesn't exist
at.......此处省略
我看到这个报错后就像,既然找不到表嘛我就新建一个嘛,我在test数据库下新建了一个news_table表,结果成功把数据添加进去了,而且我建的这个表只有部分字段,缺的字段它也补全了。原本我打算就此了事,结果往后的学习中我知道这表是自动生成的,而不是必须我手动在数据库新建。所以我开始寻求这个问题的答案。
这里我顺便引申一下吧,在bibernate.cfg.xml配置文件中的hibernate-configuration下的session-factory下添加<property name="hbm2ddl.auto">值</property>。值为以下四种
create:
每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop :
每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:
最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动 更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate :
每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
我在网上搜了一下,遇到这个问题的人挺多的。有人回答说“把hibernate映射文件中的catalog=hibernate属性去掉”,结果我发现我没有,所以不可能是这个原因。有人回答说“看一下映射文件中的主键类型是不是java.lang.String,是的话改成java.lang.Integer”,我检查了一下,我是用的Integer。有人回答说是“<property name="hbm2ddl.auto">update</property>”的问题,于是我试了一下换成create,结果还是不行,而且我试了下手动新建,结果这次不仅值没插进去,反而给我把表删掉了。有人说我肯定是哪个字符串写错了,我检查了几遍都没问题。还有人说版本不对,所以我换了很多版本,用hibernate-core-5.0.0.Final.jar的时候还出现了个org.hibernate.MappingException: Unknown entity:,所以都不知道原问题解决没,其实应该是没解决。真心没法了。
正当我准备放弃的时候,我在csdn上看到一篇文章,他提出了一个新的解决办法,虽然他说他不知道为什么。其实很简单,就是数据库方言设置有问题。
Hibernate的底层仍然是用的SQL语句执行数据库操作,虽然所有的关系型数据库都支持SQL,但是不同的数据库都进行了扩展,在语法上存在一定差异,举例来说,我们在MySQL数据库里进行分页查询,只需使用limit关键字就可以了;而标准SQL并不支持limit关键字,例如Oracle则需要使用行内视图的方式来进行分页。所以Hibernate提供了指定数据库方言的办法。
使用<property name="dialect">方言</property>来设置方言,比如MySQL支持
1、org.hibernate.dialect.MySQLDialect;
2、org.hibernate.dialect.MySQLInnoDBDialect;
3、org.hibernate.dialect.MySQLMyISAMDialect
三种方言,这个可以在hibernate-release-x.x.x.Final/project/etc/hibernate.properties文件中查到。
而我的错误在于照搬示例上用的org.hibernate.dialect.MySQLInnoDBDialect;方言。我改成org.hibernate.dialect.MySQLDialect;成功运行。方言的设定与数据库版本也有关系,大家试着弄一个适合的吧,有时候还会涉及到事务的 支持与冲突。大家慢慢研究吧,新手的我渴望大家能给我一些指正和扩展。谢谢!