我目前正在大型数据库的某些表中启用UTF-8字符。这些表已经是MS-SQL类型NVARCHAR。另外,我也有几个使用VARCHAR的字段。
Hibernate与JDBC驱动程序的交互存在一个众所周知的问题。简而言之,Hibernate /
JDBC生成的SQL会将所有字符串作为Unicode传递,而不管底层的SQL类型如何。将数据库中的非unicode(varchar)字段与Unicode输入字符串进行比较时,该列的索引与编码不匹配,因此将执行全表扫描。在JDBC驱动程序(JTDS和MS版本)中,都有一个参数将Unicode字符串作为ASCII传递,但这是一个全有或全无的命题,不允许将国际字符输入到数据库中。
我在这个问题上见过的大多数帖子都提出了以下两种解决方案之一-1)将数据库中的所有内容更改为NVARCHAR或2)设置sendStringParametersAsUnicode=false,然后我的问题是这-是否存在用于VARCHAR的已知解决方案和NVARCHAR在一起玩的很好吗?由于下游依赖性和其他外部问题,将所有内容更改为NVARCHAR对我的环境来说是一个巨大的 问题。
我决定尝试这种方法,使其在不接触数据库的情况下也 _可能_起作用。为此,我为NVARCHAR字段创建了自定义类型。这需要JDBC4驱动程序(使用Microsoft的驱动程序)和Hibernate3.6.0。sendStringParametersAsUnicode为false。
这是方法,我仍在验证它的正确性-来自经验超过我的人的任何评论都值得欢迎
html" target="_blank">添加新的方言以支持新的数据类型
public class SQLAddNVarCharDialect extends SQLServerDialect {
public SQLAddNVarCharDialect(){
super();
registerColumnType( Types.NVARCHAR, 8000, "nvarchar($1)" );
registerColumnType( Types.NVARCHAR, "nvarchar(255)" );
}
}
添加新的类型。注意setNString
在nullSafeSet
public class NStringUserType implements UserType {
@Override
public Object assemble(Serializable arg0, Object owner)
throws HibernateException {
return deepCopy(arg0);
}
@Override
public Object deepCopy(Object arg0) throws HibernateException {
if(arg0==null) return null;
return arg0.toString();
}
@Override
public Serializable disassemble(Object arg0) throws HibernateException {
return (Serializable)deepCopy(arg0);
}
@Override
public boolean equals(Object arg0, Object arg1) throws HibernateException {
if(arg0 == null )
return arg1 == null;
return arg0.equals(arg1);
}
@Override
public int hashCode(Object arg0) throws HibernateException {
return arg0.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if(value == null)
st.setNull(index,Types.NVARCHAR);
else
st.setNString(index, value.toString());
}
@Override
public Object replace(Object arg0, Object target, Object owner)
throws HibernateException {
return deepCopy(arg0);
}
@Override
public Class returnedClass() {
return String.class;
}
@Override
public int[] sqlTypes() {
return new int[]{Types.NVARCHAR};
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
throws HibernateException, SQLException {
String result = resultSet.getString(names[0]);
return result == null || result.trim().length() == 0
? null : result;
}
}
更新所有NVARCHAR字段的映射
<property name="firstName" type="NStringUserType">
<column name="firstName" length="40" not-null="false" />
</property>
之前的原始SQL(带有sendUnicode .. = true):
exec sp_prepexec @p1 output,N'@P0 nvarchar(4000),@P1 datetime,@P2 varchar(8000),@P3 nvarchar(4000),@P4 nvarchar(4000),@P5 nvarchar(4000),@P6 nvarchar(4000)... ,N'update Account set ... where AccountId=@P35
之后:
exec sp_prepexec @p1 output,N'@P0 varchar(8000),@P1 .... @P6 nvarchar(4000),@P7 ... ,N'update Account set ... Validated=@P4, prefix=@P5, firstName=@P6 ... where AccountId=@P35
似乎对“ SELECT ..”工作类似。”
Microsoft SQL Server,数据库中的列定义为NVARCHAR,但在Java代码中定义为。 Hibernate失败,验证错误如下: 原因:org.hibernate.tool.schema.spi.schemaManagementException:模式验证:在表[Table_Name]中的列[Column_Name]中遇到错误的列类型;找到[nvarchar(types#nvarc
问题内容: 所有,我都有一个大型(不可避免的)动态SQL查询。由于选择标准中字段的数量,包含动态SQL的字符串的长度超过4000个字符。现在,我知道为设置了最大4000 ,但是在Server Profiler中查看了已执行的SQL语句 似乎可以正常工作(!?),对于另一个也很大的查询,它抛出与此4000极限(!?)相关的错误,它基本上会在此4000极限之后修剪所有SQL,并给我留下语法错误。尽管在
总之,我有一个大型(不可避免的)动态SQL查询。由于选择条件中的字段数量,包含动态SQL的字符串增加了4000个字符。现在,我了解到的最大值设置为4000,但是查看在服务器探查器中执行的SQL语句 似乎有效(!?),对于另一个同样大的查询,它会抛出一个与4000限制(!?)相关的错误,它基本上会在4000个限制之后修剪所有SQL,并给我留下一个语法错误。尽管在探查器中出现了这一点,它还是完整地显示
问题内容: 仅仅是支持多字节字符吗?如果是这样的话,除了存储方面的问题,真的有什么要使用的varchars吗? 问题答案: 一列可以存储任何数据。甲varchar柱被限制为一个8位的代码页。有人认为varchar应该使用它,因为它占用更少的空间。我相信这不是正确的答案。代码页不兼容是一种痛苦,而Unicode是解决代码页问题的方法。如今,有了便宜的磁盘和内存,实际上没有理由再浪费时间浪费代码页了。
问题内容: 我存储的名字和姓氏各不超过30个字符。哪个更好还是。 我已阅读,尽可能多的空间两倍占用比和用于国际化。 那么您建议我使用什么:或? 还请让我知道两者的性能。两者的性能相同还是不同?因为空间不是太大的问题。问题是表现。 问题答案: 基本上,nvarchar意味着您可以处理很多字母,而不仅仅是普通英语。从技术上讲,它意味着支持unicode,而不仅仅是ANSI。这意味着全角字符或大约是空格
问题内容: 在为应用程序构建架构时遇到一个问题。 何时使用和。我的意思是应该使用它的确切用例。我也曾在网上冲浪,但我能够得到确切的答案。 任何人都可以提出一些确切的用例。 问题答案: 这是针对Microsoft SQL Server的 : 是 Unicode- 每个字符2个字节,因此最大。10亿个字符;可以处理东亚语,阿拉伯语,希伯来语,西里尔字母等字符。 就是 非Unicode -每个字符1个字