Spring Boot +Hibernate + jpa 通过实体映射生成数据库中的表
遇到几个问题:
1.表不能自动生成到数据库中:
在application.yml 中加入配置 :
hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构。
create:
每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop :
每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:
最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate :
每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
!!!!!!!!!对于这一点,要补充一下,若设置为validate的话,数据库本来没建序列,而代码实体类里,定义了序列,是会报错的,因为校验不成功,只有用update才可以把实体里自定义的序列加进数据库
还要注意schema写的位置,位置不对的话,spring-boot-jpa自动建表就一直没反应!!!!!快被气死了,觉得没问题的问题就是死活跑不通。。。。。。踩坑。。。。。。
2.对于标题报的错是因为:
在实体里设置了主键自增长
我把它注释掉了。解决了问题,表自动生成到数据库中了,有人说是因为:
是因为oracle不支持identity,支持是sequence,把
@GeneratedValue(strategy = GenerationType.IDENTITY)
修改为
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "abc_seq")
@SequenceGenerator
(name = "
abc_seq", initialValue =
1
, allocationSize =
1
, sequenceName =
"ABC_SEQUENCE"
)
大概就是这样吧,springboot jpa 自动建表且建序列,oracle数据库,注意一下application.yml的配置,要加schema,autoddl要设置成update
以及实体类中自增主键的设置:用加序列生成策略,自定义名字。
最好是每张表自己单独用一个属于自己的序列,省的搞乱,也省的麻烦,尤其是表数据经常改变的。
踩过一次坑,又踩了一次,红色字体都是更新以及新的心得。
还有一种解决没建序列的方法,但我不太懂为什么这样就可以了,这种方法的话,autoddl=validate 也能跑通过,同事是这样解决的:
如果把increment改成sequence,是不是就跟上面的效果一样了,这点还没试验
对于@GenericGenerator这个注解,里面中的strategy策略
参考一下这篇博客:
https://blog.csdn.net/jxchallenger/article/details/78567641
Hibernate源码我们找到了Hibernate预定义strategy ,共14种:
对于这些策略的详解,找到一篇博客,很详细实用易懂:https://www.cnblogs.com/hoobey/p/5508992.html
Hibernate中唯一一种最简单通用的主键生成器就是uuid。虽然是个32位难读的长字符串,但是它没有跨数据库的问题,将来切换数据库极其简单方便,推荐使用!
identity 针对于 mysql,不适用oracle,oracle要用sequence,前提是要在数据库先建序列,如果不提前建的话,那就要用我上面红字那种方式,在实体里指定名字,且把application中的autoddl设置为update
increment:由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。
Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
官方文档:只有在没有其他进程往同一张表中插入数据时才能使用,在集群下不要使用。
特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境