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

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

@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 с реализацией JPA в Hibernate (версия 3.2.1.ga).

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


person Steve Kuo    schedule 14.01.2009    source источник


Ответы (4)


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

INSERT INTO <Table Name> DEFAULT VALUES

Это разрешенный синтаксис SQL, поддерживаемый, например, Microsoft SQL. Сервер, 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 для целевой марки СУБД.

import org.hibernate.cfg.Configuration;

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

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

person Bill Karwin    schedule 14.01.2009

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

person behoph    schedule 07.09.2012
comment
Я использовал «ключ» и «значение» в качестве имен столбцов. Упс. - person Ian Newland; 07.05.2016

Другая ситуация, когда у вас может возникнуть это исключение, — это когда вы зарезервировали слова в качестве столбцов для таблицы. Например, «to» и «from» не являются подходящими именами столбцов для MySQL. Явный баг в Hibernate, он не проверяет такие столбцы и более того продолжает работать без ошибок, даже если таблица не создана.

person Stepan Yakovenko    schedule 10.11.2012
comment
Это был действительно большой намек. - person kailash gaur; 09.05.2017

Убедитесь, что spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect имеет правильную версию MySQL.

person Makatun    schedule 09.04.2020