У меня есть следующие классы сущностей 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




Стандартный 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 для целевой марки СУБД.
import org.hibernate.cfg.Configuration;
Configuration cfg = new Configuration();
cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
Вы также можете указать свойства, поместив файл с именем hibernate.properties в корневой каталог пути к классам.
Если в вашем операторе SQL нет ошибки, вы можете проверить имя столбца таблицы, поскольку оно может содержать предопределенное имя, которое использует Mysql; например, "столбец", который нельзя использовать в качестве имени столбца таблицы
Другая ситуация, когда у вас может быть это исключение, - это когда вы зарезервировали слова в качестве столбцов для таблицы. Например, «to» и «from» не подходят для имен столбцов MySQL. Очевидно, что это ошибка Hibernate, что он не проверяет такие столбцы и, более того, продолжает работать без ошибок, даже если таблица не создана.
Это был действительно большой намек.
Убедитесь, что spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect имеет правильную версию MySQL.
Я использовал «ключ» и «значение» в качестве имен столбцов. Вупс.