问题:
org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [create table t_user (uid varchar(255) not null auto_increment, username varchar(255), password varchar(255), address varchar(255), primary key (uid))]
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:431)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:420)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.createTable(SchemaMigratorImpl.java:236)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:167)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:60)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:133)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:470)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at com.watsun.hibernatetest.HibernateDemo.testAdd(HibernateDemo.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Incorrect column specifier for column 'uid'
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Statement.executeUpdate(Statement.java:1316)
at com.mysql.jdbc.Statement.executeUpdate(Statement.java:1235)
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56)
... 35 more
排查后发现是hibernate映射配置文件中,uid的类型和generator设置主键生成方式的对不上。
uid类型是String,generator不能使用native,改成使用uuid就好了,或者把String类型改成Integer。
附上hibernate的主键生成方式:
1.assigned算法
主键由外部程序负责生成,无须Hibernate参与,因此需要应用程序在执行save()之前为对象分配一个标示符。这是generator元素没有指定时的默认生成策略。
当选择 assigned 生成器时,除非有一个version或者timestamp属性,或者你定义了Interceptor.isUnsaved(),否则需要让Hibernate使用unsaved-value=“undefined”,强制Hibernate查询参数库来确定一个实例是瞬时的(transient)还是托管的(detached)。
如例:<id name="id" type="long" column="ID" unsaved-value="undefined">
<generator class="assigned"></generator>
</id>
2.hilo算法
使用hi/lo(高/低位)算法高效地生成long、short或者int类型的标示符。高/低位算法生成的标示符只在一个特定的数据库中是唯一的,需要额外的数据库表或字段提供高位值来源。
hilo生成器需要一个“特殊”的数据库表来保存下一个可用的“hi”值,使用该算法是,需要通过以下3个参数来指定数据库中的表信息来保存“hi”值。table:保存ID的表名。
column:保存ID的字段名。
max_lo:最大编号。
如例:
<id name="id" type="long" column="ID">
<generator class="hilo">
<param name="table">unique_id</param>
<param name="column">id_value</param>
<param name="max_lo">100</param>
</generator>
</id>
3.seqhilo算法
与hilo类似,通过hi/lo算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。
seqhilo生成器使用一个Oracle风格的序列,这要求数据库支持序列。它需要包括以下两个参数。sequence:序列名。
column:最大编号。
如例:
<id name="id" type="long" column="ID">
<generator class="seqhilo">
<param name="sequence">unique_id</param>
<param name="max_lo">100</param>
</generator>
</id>
4.increment算法
increment标识主键按数值顺序递增。此方式的实现机制为,在当前应用实例中维持一个变量,以保存当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。
这种方式可能产生的问题是:如果当前有多个实例访问统一数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
如例:<id name="id" type="long" column="ID" >
<generator class="increment"></generator>
</id>
5.identity算法
identity采用数据库提供的主键生成机制,如DB2、MySQL、Sybase、MSSQL中的主键生成机制,这需要这些数据库内部支持标识字段。
如例:<id name="id" type="long" column="ID" unsaved-value="0">
<generator class="identity"></generator>
</id>
6.sequence算法
sequence采用数据库提供的Sequence机制生成主键,如Oracle中的Sequence。对于内部支持序列的数据库(DB2、Oracle、PostgreSQL、Interbase、McKoi、SAPDB),你可以使用Sequence风格的关键字生成。
sequence与seqhilo都使用数据库的序列,但是不同的是,sequence是使用序列生成的ID,而seqhilo是用序列来保存程序生成的ID,该ID由算法自动生成。
如例:<id name="id" type="long" column="ID">
<generator class="sequence">
<param name="sequence">unique_id_sequence</param>
</generator>
</id>
7.native算法
由Hibernate根据底层数据库自行判断采用identity、hilo和sequence其中一种作为主键生成方式。
对于跨平台开发,native策略会从identity、hilo和sequence中进行选择,选择哪一个,这取决于底层数据库的支持能力。
如例:<id name="id" type="long" column="ID">
<generator class="native"></generator>
</id>
8.uuid.hex算法
由Hibernate基于128位唯一产生算法UUID生成16进制数值(编码后以长度32的字符串表示)作为主键。
UUID包含:IP地址、JVM的启动时间(精确到1/4秒)、系统时间和一个计数器值(在JVM中唯一)。在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了。
一般而言,利用uuid.hex方式生成的主键将提供最好的性能和数据库平台适应性。
如例:<id name="id" type="long" column="ID">
<generator class="uuid.hex"></generator>
</id>
9.uuid.string算法
与 uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些数据库中可能出现问题(如PostgreSQL)
如例:<id name="id" type="long" column="ID">
<generator class="uuid.string"></generator>
</id>
10.foreign算法
使用另外一个相关联的对象的标识符。通常和</one-to-one>联合起来使用。
如例:<id name="id" type="long" column="ID">
<generator class="foreign"></generator>
</id>
11.select算法
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
如例(我们定义一个命名为MainImportantNumber的唯一值属性,它是一个自然键『natural key』,命名为ID的代理键的值由触发器『surrogate key』生成):<id name="id" type="long" column="ID">
<generator class="select">
<param name="key">MainImportantNumber</param>
</generator>
</id>
资料引用来源:https://blog.youkuaiyun.com/u010046905/article/details/45600221