#hibernate #jpa #postgresql-9.1
#гибернация #jpa #postgresql-9.1
Вопрос:
Редактировать: РЕШАЕМАЯ правильно. Я нашел то, что меня смутило. Я использую 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 в целом, или какая-то конфигурация hibernate отсутствует?
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. Если вы удалите свойство, связанное с диалектом hibernate, будет ли оно работать? На самом деле
@Entity(""..."")
конструкция заключается в том, чтобы заставить поставщика JPA использовать предоставленное точное значение (т. Е. использовать точный регистр имени таблицы). Не знаю, почему в вашем случае это творит какую-то магию.2. Я пробовал без диалекта, исходный Sample.java не работает, модифицированные работы, также пытался использовать диалект MySQL вместо PostgreSQL, просто ожидая увидеть предупреждения или ошибки, результат тот же, похоже, что a) диалект игнорируется b) диалект не используется при построении SQL-запросов, но, вероятно, только для поведения, специфичного для поставщика, такого как разбивка на страницы, например.
3. а что, если бы вы попробовали использовать свойства JPA для подключения к JDBC ( vogella.de/articles/JavaPersistenceAPI /… ) и удалить свойства, связанные с диалектом и гибернацией? Каково точное название таблицы в вашей базе данных?
4. Скрипт PostgreSQL: СОЗДАЙТЕ ТАБЛИЦУ «SAMPLE» (целое число «ID» НЕ равно нулю, символ «TITLE», изменяющийся (100), НЕ равен НУЛЮ, ОГРАНИЧЕНИЕ ПЕРВИЧНОГО КЛЮЧА «SAMPLE_ID_PK» («ID») ) С ПОМОЩЬЮ ( OIDS= FALSE); ИЗМЕНИТЕ ВЛАДЕЛЬЦА ТАБЛИЦЫ «SAMPLE» НА postgres;
Ответ №1:
@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.
Следовательно, для запроса «тестовой» таблицы вам нужно будет выполнить SELECT * FROM "TeSt"
(не SELECT * FROM TeSt
).
Итак, если вы создаете таблицу с помощью CREATE TABLE "SAMPLE"
, вам нужно указать @Table(name=""SAMPLE"")
, чтобы она заработала.
Комментарии:
1. Добавлено объяснение в заголовок моего вопроса. Спасибо.