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 не проверяет такие столбцы и, кроме того, продолжает работать без ошибок, даже если таблица не создана.