解决思路:
1、解决关键字问题;
2、解决大小写敏感的问题。
首先解决第一个问题,这里有几种方式
(1)将表名或字段名用方括号([])括起来
XML
<property name="context" type="string" >
<column name="[CONTEXT]" length="255" not-null="true" />
</property>
注解
@Column(name = "[CONTEXT]", nullable = false)
private String context;
(2)将表名或字段名用双引号(")括起来
XML
<property name="context" type="string" >
<column name='"CONTEXT"' length="255" not-null="true" />
</property>
注解
@Column(name = "\"CONTEXT\"", nullable = false)
private String context;
解决了第一个问题之后我们再来解决第二个问题,由于Hibernate默认讲所有表名、字段名都转换成小写字母,所以经过转换之后的SQL语句类似于SELECT obj."context" FROM obj;这样的SQL在Oracle中运行也有问题,而SELECT OBJ."CONTEXT" FROM OBJ;这样的SQL运行就问题,所以就需要解决Hibernate大小写的问题,Hibernate控制表名和字段名大小写的配置类为org.hibernate.cfg.ImprovedNamingStrategy,所以我们现在要重写Hibernate的命名策略。
总共需要两个步骤:
(1)写一个替代Hibernate默认命名规则类
package com.xjj.framework.hibernate.cfg;
import java.io.Serializable;
import java.util.Locale;
import org.hibernate.AssertionFailure;
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.internal.util.StringHelper;
public class DMNamingStrategy extends ImprovedNamingStrategy implements
NamingStrategy, Serializable {
/**
* A convenient singleton instance
*/
public static final NamingStrategy INSTANCE = new DMNamingStrategy();
/**
* Return the unqualified class name, mixed case converted to
* underscores
*/
@Override
public String classToTableName(String className) {
return addUnderscores( StringHelper.unqualify(className) );
}
/**
* Return the full property path with underscore seperators, mixed
* case converted to underscores
*/
@Override
public String propertyToColumnName(String propertyName) {
return addUnderscores( StringHelper.unqualify(propertyName) );
}
/**
* Convert mixed case to underscores
*/
@Override
public String tableName(String tableName) {
return addUnderscores(tableName);
}
/**
* Convert mixed case to underscores
*/
@Override
public String columnName(String columnName) {
return addUnderscores(columnName);
}
protected static String addUnderscores(String name) {
StringBuilder buf = new StringBuilder( name.replace('.', '_') );
for (int i=1; i<buf.length()-1; i++) {
if (
Character.isLowerCase( buf.charAt(i-1) ) &&
Character.isUpperCase( buf.charAt(i) ) &&
Character.isLowerCase( buf.charAt(i+1) )
) {
buf.insert(i++, '_');
}
}
return buf.toString().toUpperCase(Locale.ROOT);
}
@Override
public String collectionTableName(
String ownerEntity, String ownerEntityTable, String associatedEntity, String associatedEntityTable,
String propertyName
) {
return tableName( ownerEntityTable + '_' + propertyToColumnName(propertyName) );
}
/**
* Return the argument
*/
@Override
public String joinKeyColumnName(String joinedColumn, String joinedTable) {
return columnName( joinedColumn );
}
/**
* Return the property name or propertyTableName
*/
@Override
public String foreignKeyColumnName(
String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName
) {
String header = propertyName != null ? StringHelper.unqualify( propertyName ) : propertyTableName;
if (header == null) throw new AssertionFailure("NamingStrategy not properly filled");
return columnName( header ); //+ "_" + referencedColumnName not used for backward compatibility
}
/**
* Return the column name or the unqualified property name
*/
@Override
public String logicalColumnName(String columnName, String propertyName) {
return StringHelper.isNotEmpty( columnName ) ? columnName : StringHelper.unqualify( propertyName );
}
/**
* Returns either the table name if explicit or
* if there is an associated table, the concatenation of owner entity table and associated table
* otherwise the concatenation of owner entity table and the unqualified property name
*/
@Override
public String logicalCollectionTableName(String tableName,
String ownerEntityTable, String associatedEntityTable, String propertyName
) {
if ( tableName != null ) {
return tableName;
}
else {
//use of a stringbuffer to workaround a JDK bug
return new StringBuffer(ownerEntityTable).append("_")
.append(
associatedEntityTable != null ?
associatedEntityTable :
StringHelper.unqualify( propertyName )
).toString();
}
}
/**
* Return the column name if explicit or the concatenation of the property name and the referenced column
*/
@Override
public String logicalCollectionColumnName(String columnName, String propertyName, String referencedColumn) {
return StringHelper.isNotEmpty( columnName ) ?
columnName :
StringHelper.unqualify( propertyName ) + "_" + referencedColumn;
}
}
基本上是将ImprovedNamingStrategy类拷贝过来并修改addUnderscores方法的返回值为toUpperCase即可。
(2)将命名策略配置到Hibernate的SessionFactory初始化配置上
由于我们公司是使用spring-boot来进行开发的,所以这里给出spring-boot的配置,是经过验证的,XML配置尚未经过验证,配错了我不背锅哦。
spring-boot 1.3.8版本配置
spring.jpa.hibernate.naming_strategy: com.xjj.framework.hibernate.cfg.DMNamingStrategy
spring-boot 1.4.0以上版本的配置
spring.jpa.hibernate.naming.physical-strategy=com.xjj.framework.hibernate.cfg.DMNamingStrategy
XML方式配置
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="namingStrategy" ref="namingStrategy" />
</bean>
以上就是解决这个问题的方案了。
参考:
1、http://blog.csdn.net/xt0916020331/article/details/49905949
2、https://my.oschina.net/moks/blog/292740