JPA с Hibernate 3.6.8.Final, PostgreSQL 9.1, SQLGrammarException - проблема с конфигурацией? Странный оператор SQL - PullRequest
5 голосов
/ 14 ноября 2011

Редактировать : решаемые Правильно. Я нашел то, что смутило меня. Я использую pgadmin для создания таблиц и других внутренних компонентов базы данных, проверено прямо сейчас: если хотя бы одна буква в имени (имя таблицы, имя столбца, имя pk и т. Д.) Находится в верхнем регистре, то pgadmin использует его в сценарии создания SQL используя двойные кавычки, PostgreSQL интерпретирует имя так, как оно написано. Если запустить следующий скрипт:

CREATE TABLE SAMPLE
(
  ID integer NOT NULL,
  TITLE character varying(100) NOT NULL,
  CONSTRAINT SAMPLE_ID_PK PRIMARY KEY (ID)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE SAMPLE
  OWNER TO postgres;_

он создает все в нижнем регистре, и оригинальная версия Sample.java работает нормально. <ч /> Что здесь не так? Эта проблема специфична для PostgreSQL 9.1 или PostgreSQL в целом, или отсутствует какая-либо конфигурация гибернации?

persistence.xml:

<persistence-unit name="com.sample.persistence.jpa" transaction-type="RESOURCE_LOCAL">
    <class>com.sample.persistence.Sample</class>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
        <property name="hibernate.connection.url" value="jdbc:postgresql:sample"/>
        <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
        <property name="hibernate.connection.username" value="postgres"/>
        <property name="hibernate.connection.password" value="postgres"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="hbm2ddl.auto" value="update"/>
    </properties>
</persistence-unit>

Sample.java

@Entity
@Table(name = "SAMPLE")
public class Sample {

    @Id
    @Column(name = "ID")
    private long id;

    @Column(name = "TITLE")
    private String title;

    public String getTitle() {
        return title;
    }
}

PersistenceMain.java:

public class PersistenceMain {


    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.sample.persistence.jpa");
        EntityManager em = emf.createEntityManager();

        Sample sample = em.find(Sample.class, 1l);

        System.out.println("Sample Title: " + sample.getTitle());

        em.close();

        emf.close();
    }
}

Исключение:

...
Hibernate: 
    select
        sample0_.ID as ID0_0_,
        sample0_.TITLE as TITLE0_0_ 
    from
        SAMPLE sample0_ 
    where
        sample0_.ID=?
Exception in thread "main" javax.persistence.PersistenceException:     org.hibernate.exception.SQLGrammarException: could not load an entity:   [com.sample.persistence.Sample#1]
 ...
Caused by: org.postgresql.util.PSQLException: ERROR: relation "sample" does not exist
 ...

Очевидно, этот оператор SQL выше:

select
    sample0_.ID as ID0_0_,
    sample0_.TITLE as TITLE0_0_ 
from
    SAMPLE sample0_ 
where
    sample0_.ID=?

не выполняется успешно из самого PostgreSQL (из pgadmin).

Но если я изменю Sample.java на:

@Entity
@Table(name = "\"SAMPLE\"")
public class Sample {

    @Id
    @Column(name = "\"ID\"")
    private long id;

    @Column(name = "\"TITLE\"")
    private String title;

    public String getTitle() {
        return title;
    }
}

что странно, это работает.

Hibernate: 
    select
        sample0_."ID" as ID1_0_0_,
        sample0_."TITLE" as TITLE2_0_0_ 
    from
        "SAMPLE" sample0_ 
    where
        sample0_."ID"=?
Sample Title: Sample

Является ли hibernate.dialect здесь бесполезным или он не работает должным образом с PostgreSQL 9.1? Кроме того, я не хотел бы вводить имена столбцов, если они совпадают с полями, но в верхнем регистре это также возможно?

Спасибо.

1 Ответ

4 голосов
/ 14 ноября 2011

Конструкция @Table("\"...\"") предназначена для того, чтобы заставить JPA-провайдера использовать точное предоставленное вами значение (т.е. использовать точный регистр имени таблицы).

Более того, в мире PostgreSQL это похоже. Если вы вызовете CREATE TABLE и укажете имя таблицы в кавычках, это создаст таблицу с указанным вами точным именем (не только регистр, но и семантика - таким образом вы даже сможете создать таблицу с именем TABLE): *

CREATE TABLE "TeSt" ( id int PRIMARY KEY NOT NULL )

приведет к таблице TeSt8 .

CREATE TABLE TeSt2 ( id int PRIMARY KEY NOT NULL )

приведет к таблице test2 .

Следовательно, для запроса таблицы "TeSt" вам нужно выполнить SELECT * FROM "TeSt" ( not SELECT * FROM TeSt).

Итак, если вы создаете таблицу с CREATE TABLE "SAMPLE", вам нужно указать @Table(name="\"SAMPLE\""), чтобы она заработала.

...