Hibernate генерирует недопустимый SQL-запрос с MySQL

У меня есть следующие классы сущностей JPA (пример case). Дом принадлежит одной улице. У улицы много домов.

@Entity
public class House {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Integer id;

    public String name    

    @ManyToOne
    public Street street;
}

@Entity
public class Street {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Integer id;

    @OneToMany(mappedBy="street")
    public Set<House> houses;
}

У меня есть тип генерации, установленный для идентификатора, который должен автоматически назначать новый идентификатор.

Создавая новый Дом с новой Улицей, я должен сначала создать и перенести улицу, а затем Дом. Это связано с тем, что у меня нет CascadeType, установленного в PERSIST, поэтому это нужно сделать вручную [1]. Однако при вставке вновь созданной улицы:

Street street = new Street();
entityManager.persist(street);

Hibernate/JPA генерирует следующий SQL-запрос:

insert into Street default values

который MySQL не любит.

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 'default values' at line 1 

Любые идеи, почему? Я использую Java 6, MySQL 5.0.67 с введением Hibernate JPA (версия 3.2.1.ga).

[1] EJB 3 в действии страницы 318-319

Ответ 1

Стандартный SQL указывает этот необязательный синтаксис для INSERT:

INSERT INTO <Table Name> DEFAULT VALUES

Это законный синтаксис SQL, поддерживаемый, например, Microsoft SQL Server, PostgreSQL и SQLite, но не Oracle, IBM DB2 или MySQL.

MySQL поддерживает другой синтаксис, который обеспечивает тот же результат:

INSERT INTO <Table Name> () VALUES ()

INSERT INTO <Table Name> (col1, col2, col3) VALUES (DEFAULT, DEFAULT, DEFAULT)

В Hibernate вы должны настроить диалект SQL правильно, и это до Hibernate для генерации действительного SQL для целевой марки RDBMS.

import org.hibernate.cfg.Configuration;

Configuration cfg = new Configuration();
cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");

Вы также можете указать свойства, поместив файл с именем hibernate.properties в корневой каталог пути к классам.

Ответ 2

Если у вас нет ошибки в инструкции SQL, вам может потребоваться проверить имя столбца таблицы, поскольку оно может содержать предопределенное имя, которое использует Mysql; например "столбец", который нельзя использовать в качестве имени столбца таблицы

Ответ 3

Другая ситуация, когда вы можете иметь это исключение, - это когда вы зарезервировали слова в качестве столбцов для таблицы. Например, 'to' и 'from' не подходят именам clumn для MySQL. Очевидно, что ошибка в Hibernate не проверяет такие столбцы и, кроме того, продолжает работать без ошибок, даже если таблица не создана.