Hibernate MySQL方言配置遇到的坑
阿新 • • 發佈:2018-12-10
環境 hibernate5.2.17、MySQL5.5,採用JPA註解配置
1. The First
配置檔案:peresistence.xml
//...其它略...
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
執行TestApp,報了異常
異常:
2018-09-15 15:46:06 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
...略....
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 21
原因:
MyISAM引擎不支援外來鍵,建立不了表並報錯 。
MySQLDialect是MySQL5.X之前的版本,其預設的引擎是MyISAM。部分原始碼如下:
private MySQLStorageEngine storageEngine;
//org.hibernate.dialect.MySQLDialect.getDefaultMySQLStorageEngine()
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return MyISAMStorageEngine.INSTANCE;
}
//org.hibernate.dialect.MyISAMStorageEngine.getTableTypeString(String)
@Override
public String getTableTypeString(String engineKeyword) {
return String.format( " %s=MyISAM", engineKeyword );
}
所以更改配置
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
2. The second
改為上面的配置後,執行,未報異常,表建立成功。
表如下:
等等,外來鍵呢 ??!??
去控制檯檢視sql
發現儲存引擎還是 engine=MyISAM ,於是又去檢視 MySQL5Dialect 的原始碼。
//org.hibernate.dialect.MySQL5Dialect
public class MySQL5Dialect extends MySQLDialect{}
MySQL5Dialect 繼承自 MySQLDialect,發現其原始碼中並沒有更改預設儲存引擎,
所以然是 MyISAM。但是MySQL5Dialect並沒有報異常,能夠建立表。
PS:在Navicat中手動新增外來鍵,選擇外來鍵的時候有如下提示:
點選儲存外來鍵,然後外來鍵消失。這時候就要注意儲存引擎了。
3. The third
改為如下配置:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL55Dialect"/>
這次OK了。其原始碼如下,繼承自 MySQL5Dialect ,但 以看到改用了InnoDB儲存引擎。
//org.hibernate.dialect.MySQL55Dialect
public class MySQL55Dialect extends MySQL5Dialect {
@Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE;
}
}
//org.hibernate.dialect.InnoDBStorageEngine
public class InnoDBStorageEngine implements MySQLStorageEngine{
public static final MySQLStorageEngine INSTANCE = new InnoDBStorageEngine();
@Override
public String getTableTypeString(String engineKeyword) {
return String.format( " %s=InnoDB", engineKeyword );
}
}
如下也行。
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL57Dialect"/>
//MySQL57Dialect繼承自MySQL55Dialect,添加了一些新的資料格式。
//org.hibernate.dialect.MySQL57Dialect
public class MySQL57Dialect extends MySQL55Dialect {}
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
// MySQL5InnoDBDialect。已棄用,所以不推薦。
/** A Dialect for MySQL 5 using InnoDB engine
*
* @author Gavin King,
* @author Scott Marlow
* @deprecated Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.
*/
@Deprecated
public class MySQL5InnoDBDialect extends MySQL5Dialect {
@Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE;
}
}
但是使用如下方言,又雙叒叕報錯了,建立不了表並報錯。
org.hibernate.dialect.MySQLInnoDBDialect
原始碼如下,繼承自MySQLDialect ,又棄用了,但是它設定了InnDB儲存引擎 。為什麼報錯 ???這個坑沒爬上來,求指點。
/**
* A Dialect for MySQL using InnoDB engine
*
* @author Gavin King
* @deprecated Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.
*/
@Deprecated
public class MySQLInnoDBDialect extends MySQLDialect {
@Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE;
}
}
附:
TestApp
public class TestApp{
@Test
public void testDialect(){
EntityManagerFactory entityManagerFactory = HbnUtil.getEntityManager();
}
}
Entity
Entity
@Table(name = "Metar")
@DynamicInsert
public class Metar {
@Id
@GenericGenerator(name = "uuid", strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String mid;
....略...
@OneToMany(targetEntity = SkyCondition.class, mappedBy = "metar", fetch = FetchType.EAGER,cascade=CascadeType.ALL)
private Set<SkyCondition> skyConditionsSet;
....略setter/getter...
}
@Entity
@Table(name = "sky_condition")
public class SkyCondition {
@Id
@GenericGenerator(name = "uuid", strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String skyId;
@ManyToOne(targetEntity = Metar.class, fetch = FetchType.EAGER)
@JoinColumn(name = "metar_id",referencedColumnName="mid")
private Metar metar;
}