欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate MySQL方言配置遇到的坑

程序员文章站 2022-06-20 10:43:36
...

环境 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

  改为上面的配置后,运行,未报异常,表创建成功。

表如下:
Hibernate MySQL方言配置遇到的坑

等等,外键呢 ??!??
 去控制台查看sql

Hibernate MySQL方言配置遇到的坑

  发现存储引擎还是 engine=MyISAM ,于是又去查看 MySQL5Dialect 的源码。

//org.hibernate.dialect.MySQL5Dialect
public class MySQL5Dialect extends MySQLDialect{}

  MySQL5Dialect 继承自 MySQLDialect,发现其源码中并没有更改默认存储引擎,
所以然是 MyISAM。但是MySQL5Dialect并没有报异常,能够创建表。

PS:在Navicat中手动添加外键,选择外键的时候有如下提示:

Hibernate MySQL方言配置遇到的坑
点击保存外键,然后外键消失。这时候就要注意存储引擎了。

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;

}

参考:
MySQL存储引擎中的MyISAM和InnoDB区别详解

Hibernate的dialect 方言大全

相关标签: MySQL hibernate