我有一些与索引名称和约束名称的大小写敏感性有关的问题
在休眠生成的数据库模式中。我的意图是使它们大写,但
我无法实现。
这些是系统库/组件的主要功能:
针对PostgreSQL 9.3数据库的Hibernate 4.3.6。
我正在为实体使用注释,并尝试使用以下语句生成架构:
Persistence.createEntityManagerFactory(“ vegaUnitDDL”)。createEntityManager();
接下来是我用来尝试不同选项的测试实体:
package net.test.software.test001.persistence.jpa;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;
@Entity
@Table(name="\"V_TEST\""
, catalog="\"VEGA_DB_SCHEMA\""
, indexes = {@Index(name="V_TEST_IDX", columnList="`TYPE`")}
)
public class Test {
@Column(name="\"TEST_ID\"")
@Id
private long id = 0;
@Column(name="\"TYPE\"", nullable=false)
private String type = null;
}
persistene.xml是:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.co/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="vegaUnitDDL" transaction-type="RESOURCE_LOCAL">
<!-- -->
<class>net.test.software.test001.persistence.jpa.Test</class>
<!-- -->
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/VEGA_DB"/>
<property name="javax.persistence.jdbc.user" value="VEGA_USER"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
启动模式生成的主要类:
package net.test.software.test001.persistence.jpa.model;
import javax.persistence.Persistence;
public class SchemaGenerator {
public SchemaGenerator() {
System.out.println("Creating the entity manager factory.");
Persistence.createEntityManagerFactory("vegaUnitDDL").createEntityManager();
System.out.println("DB schema created.");
}
public static void main(String[] args) {
try {
new SchemaGenerator();
System.out.print("+-*.:+-*.:+-*.:+-*.:+-*.:");
System.exit(0);
} catch(Exception ex) {
ex.printStackTrace();
System.err.print(">>>>>>>>>>>>>>>>>>>>>>>>>");
System.exit(-1);
}
}
}
最后是表的ddl和pgAdmin工具返回的索引(一旦在数据库中创建了模式):
-- Table: "VEGA_DB_SCHEMA"."V_TEST"
-- DROP TABLE "VEGA_DB_SCHEMA"."V_TEST";
CREATE TABLE "VEGA_DB_SCHEMA"."V_TEST"
(
"TEST_ID" bigint NOT NULL,
"TYPE" character varying(255) NOT NULL,
CONSTRAINT "V_TEST_pkey" PRIMARY KEY ("TEST_ID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE "VEGA_DB_SCHEMA"."V_TEST"
OWNER TO "VEGA_SYS";
-- Index: "VEGA_DB_SCHEMA".v_test_type_idx
-- DROP INDEX "VEGA_DB_SCHEMA".v_test_type_idx;
CREATE INDEX v_test_type_idx
ON "VEGA_DB_SCHEMA"."V_TEST"
USING btree
("TYPE" COLLATE pg_catalog."default");
问题:
1.-如何获取V_TEST_pkey为全大写字母?我可以使用的persistence.xml文件中是否有任何属性?
2.-是否必须在回勾之间在@Index的columnList参数中写入列?他们不应该在双引号之间吗? (即columnList =“ \” TYPE \“”代替columnList =“`TYPE`”)
如果要让休眠将其创建为大写字母,则假定必须在@Column批注中用双引号括起来。那就是我在Test类中声明它的方式。但是,对于@Index批注,如果我使用\“ TYPE \”而不是`TYPE`,它将失败。
我必须进行一些调试才能发现休眠如何对其进行管理。
A)首先,让我们看看休眠解析任何列信息的方式:在此过程中,它在列的逻辑名(用于内部引用的名称)与其物理名称(当表在DDL中声明的名称)之间建立映射被建造。它还使物理名称反向映射到逻辑名称。逻辑名称仅供库内部使用,并取决于休眠命名策略。为了获得它,hibernate通过一系列操作处理java注释@Column中指示的名称:
它开始将双引号变成反引号(\“ TEST_ID \”->`TEST_ID`; \“ TYPE \”->`TYPE`)
final String columnName = nameNormalizer.normalizeIdentifierQuoting( col.name() );
在随后的步骤中,当它获得逻辑-物理映射时,它使用命名策略来查看逻辑名称必须采用的字符串:
String logicalColumnName = mappings.getNamingStrategy().logicalColumnName(this.logicalColumnName, propertyName );
您可以在Configure类中看到后面的语句,该语句用于列绑定:
protected void addColumnBinding(SimpleValue value) {
String logicalColumnName = mappings.getNamingStrategy()
.logicalColumnName( this.logicalColumnName, propertyName );
mappings.addColumnBinding( logicalColumnName, getMappingColumn(), value.getTable());
}
在我们的例子中,仅使用persistence.xml文件中先前显示的配置,为TEST_ID和TYPE列返回的名称与作为参数传递给logicalColumnName方法的值相同,即``TEST_ID'',``TYPE''。
要保存物理列和逻辑列之间的引用,hibernate会将其放在哈希表中:在Configuration类的内部类MappingsImp的bindLogicalToPhysical方法中查看它。它用于逻辑名称的密钥是我们传递给它的所有密钥都变成小写的密钥(“ TEST_ID”->“ test_id”;“ TYPE”->“ type”):
private void bindLogicalToPhysical(String logicalName, Column physicalColumn) throws DuplicateMappingException {
final String logicalKey = logicalName.toLowerCase();
final String physicalName = physicalColumn.getQuotedName();
final String existingPhysicalName = ( String ) logicalToPhysical.put( logicalKey, physicalName );
...
}
B)现在让我们看一下休眠如何管理@Index中指示的列:
假定它必须采用columnList中列的名称并获取其逻辑名称。然后,它将通过先前在列信息解析中完成的映射来获取物理名称。只是,当获得逻辑名时,冬眠似乎被区别对待。
它采用@Index批注中编写的名称,但不应用“ idenfier quoting normalization”,因此它不会更改反勾号的双引号。然后,在地图中搜索时,它会使用名称的小写字母转换作为键,就像创建映射时一样。结果,我们必须在columList中使用`TYPE`代替\“ TYPE \”。这是一个错误吗?在我看来,将您在@Column中编写的相同字符串用作@Index的columnList参数是更有意义的。
当名称为小写字母时,所有这些问题均已解决:Hibernate: Create Index
最佳答案
Hibernate的官方文档指示对此类问题使用反引号。
http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch05.html#mapping-quotedidentifiers
stackoverflow中还有一些以前的文章:
Hibernate: use backticks for MySQL but not for HSQL
How do I put backticks in a column name called key for hibernate
关于java - Hibernate 4.3.6 DDL生成:索引中包含的列的大写名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25964864/