Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步。
方法很简单,在hibernate.cfg.xml内加入
<property name="hibernate.hbm2ddl.auto">update</property>
update:(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
在这里还有其他几个参数:
create:自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
create-drop: 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
validate: 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
测试用例:
实体类User
package com.domain; public class User { private Integer id; private String username; private String password; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + "]"; } }
User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- name: 完整类名 table:数据库表名 --> <class name="com.domain.User" table="user"> <!-- id配置表的主键 name代表表中属性 --> <id name="id" column="id"> <!-- 主键生成策略 --> <generator class="native"></generator> </id> <property name="username" column="username" type="string"></property> <property name="password" column="password" type="string"></property> <property name="age" column="age" type="integer"></property> </class> </hibernate-mapping>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 指定方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 数据库驱动 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 数据库url --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate02_1514010311</property> <!-- 数据库连接用户名 --> <property name="hibernate.connection.username">root</property> <!-- 数据库连接密码 --> <property name="hibernate.connection.password">0x3137</property> <!-- 将hibernate生成的sql语句打印到控制台 --> <property name="hibernate.show_sql">true</property> <!-- 将hibernate生成的sql语句格式化(语法缩进) --> <property name="hibernate.format_sql">true</property> <!-- 配置getCurrentSession --> <property name="hibernate.current_session_context_class">thread</property> <!-- 配置sql语句生成方式 --> <property name="hibernate.hbm2ddl.auto">update</property> <mapping resource="com/domain/User.hbm.xml" /> </session-factory> </hibernate-configuration>
HibernateUtil.java
package com.util; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static Configuration cfg; private static SessionFactory sessionFactory; static { try { cfg = new Configuration().configure(); sessionFactory = cfg.buildSessionFactory(); }catch (Exception e) { e.printStackTrace(); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
TestUser.java
package com.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.junit.Test; import com.domain.User; import com.util.HibernateUtil; public class TestUser { @Test public void saveUser() { SessionFactory sessionFactory = null; Session session = null; Transaction transaction = null; User user = new User(); user.setUsername("三哥无邪"); user.setPassword("1514010311"); user.setAge(21); try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); session.save(user); transaction.commit(); } catch (Exception e) { if (transaction!=null) { transaction.rollback(); } e.printStackTrace(); } } @Test public void updateUser() { SessionFactory sessionFactory = null; Session session = null; Transaction transaction = null; try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); User user = session.get(User.class, 1); user.setUsername("三哥无邪啊"); user.setPassword("1514010311"); user.setAge(21); session.update(user); transaction.commit(); } catch (Exception e) { if (transaction!=null) { transaction.rollback(); } e.printStackTrace(); } } @Test public void queryUser() { SessionFactory sessionFactory = null; Session session = null; Transaction transaction = null; try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); User user = session.get(User.class, 2); System.out.println("ID:"+user.getId()+" 用户名:"+user.getUsername()+" 密码:"+user.getPassword()); transaction.commit(); } catch (Exception e) { if (transaction!=null) { transaction.rollback(); } e.printStackTrace(); } } @Test public void deleteUser() { SessionFactory sessionFactory = null; Session session = null; Transaction transaction = null; try { sessionFactory = HibernateUtil.getSessionFactory(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); User user = session.get(User.class, 1); session.delete(user); transaction.commit(); } catch (Exception e) { if (transaction!=null) { transaction.rollback(); } e.printStackTrace(); } } }
测试saveUser方法,测试结果如图
自动创建了user表,然后向表内插入数据
遇到的问题
运行时出现以下错误
23:37:12,245 WARN pooling:70 - HHH10001002: Using Hibernate built-in connection pool (not for production use!) Hibernate: drop table if exists user Hibernate: create table user ( id integer not null auto_increment, username varchar(255), password varchar(255), age integer, primary key (id) ) type=MyISAM 23:37:13,303 WARN ExceptionHandlerLoggedImpl:27 - GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:440) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:424) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:315) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:166) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:135) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:121) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:155) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:309) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:452) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726) at com.util.HibernateUtil.<clinit>(HibernateUtil.java:12) at com.test.TestUser.saveUser(TestUser.java:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) 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:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'type=MyISAM' at line 7 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2819) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2768) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:894) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:732) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ... 37 more Hibernate: insert into user (username, password, age) values (?, ?, ?) 23:37:13,441 WARN SqlExceptionHelper:129 - SQL Error: 1146, SQLState: 42S02 23:37:13,441 ERROR SqlExceptionHelper:131 - Table 'hibernate02_1514010311.user' doesn't exist org.hibernate.exception.SQLGrammarException: could not execute statement at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2909) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3480) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:626) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:280) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:261) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:306) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192) at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177) at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73) at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:689) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:681) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:676) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:355) at com.sun.proxy.$Proxy26.save(Unknown Source) at com.test.TestUser.saveUser(TestUser.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) 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:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hibernate02_1514010311.user' doesn't exist at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2825) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2459) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2376) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2360) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:205) ... 51 more
在网络上查询得到结果
目前配置的mysql方言
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
根据错误内容提示很显然得知:这是MySQL的版本问题导致的问题。
实际上,在MySQL5.0以前,type=InnoDB是有效的SQL语句,但是自己用的是MySQL5.7版本,type=InnoDB不再有效了。
对于出现的错误,解决方法就是将mysql的方言改为如下
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
就此再次运行就可以自动建表了。