2009-01-14 10 views
10

Tengo las siguientes clases de entidad JPA (caso de ejemplo). Una casa pertenece a una sola calle. Una calle tiene muchas casas.Hibernate genera una consulta SQL no válida con MySQL

@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; 
} 

Tengo el tipo de generación configurado en identidad, que se supone que asigna automáticamente una nueva ID.

Al crear una nueva casa con una nueva calle, primero tengo que crear y conservar Street, seguido de House. Esto se debe a que no tengo CascadeType configurado para PERSIST, por lo que debe hacerse manualmente [1]. Sin embargo, mientras que la inserción de una calle de nueva creación:

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

Hibernate/JPA genera la siguiente consulta SQL:

insert into Street default values 

la que MySQL no le gusta.

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 

Cualquier idea por qué? Estoy usando Java 6, MySQL 5.0.67 con la implementación de JPA de Hibernate (versión 3.2.1.ga).

[1] EJB 3 en las páginas 318-319 de acción

Respuesta

11

estándar SQL especifica esta sintaxis opcional para INSERT:

INSERT INTO <Table Name> DEFAULT VALUES 

Esta es la sintaxis SQL legal, apoyado, por ejemplo, por Microsoft SQL Server, PostgreSQL y SQLite, pero no por Oracle, IBM DB2 o MySQL.

MySQL soporta otra sintaxis que logran el mismo resultado:

INSERT INTO <Table Name>() VALUES() 

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

En Hibernate, debe configure el dialecto SQL correctamente, y le toca a Hibernate generar SQL válida para la marca SGBDR de destino.

import org.hibernate.cfg.Configuration; 

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

También puede especificar las propiedades mediante la colocación de un archivo llamado hibernate.properties en un directorio raíz de la ruta de clases.

11

Si no tiene un error en su instrucción de SQL, entonces puede verificar el nombre de columna de la tabla ya que puede contener un nombre predefinido que Mysql usa; por ejemplo 'columna' que no se puede utilizar como una columna de tabla nombre

+0

Gracias, ahorraron mis horas de trabajo duro. – Heisenberg

+0

Estaba usando 'clave' y 'valor' como nombres de columna. Woops. –

7

Otra situación en la que podría tener esta excepción es cuando tiene palabras reservadas como columnas para la tabla. Por ejemplo, 'to' y 'from' no son nombres de clúster adecuados para MySQL. Obviamente, se trata de una falla en Hibernate, que no verifica tales columnas y, además, continúa funcionando sin errores, incluso si la tabla no se crea.

+0

Esto fue realmente una gran pista. –

Cuestiones relacionadas