【问题标题】:Why JPA, Hibernate and jTDS always uses varchar(8000) for String columns?为什么 JPA、Hibernate 和 jTDS 总是将 varchar(8000) 用于 String 列?
【发布时间】:2024-05-04 06:25:03
【问题描述】:

我使用 JPA (Hibernate) 和 jTDS 作为我的 jdbc 驱动程序。每当我的实体列的数据类型是字符串时,创建的预准备语句使用varchar(8000) 作为其参数。例如,我已经尝试在我的映射中使用@Column(length=50),但它似乎被忽略了。

如果我在 jTDS 连接中设置 sendStringParametersAsUnicode,它会改用 nvarchar(4000),但从不尊重我在实体中定义的长度。有什么原因吗?

【问题讨论】:

  • 它使用的是什么休眠方言?
  • 到底是什么问题?预期的行为是什么?您是在谈论生成表中列的长度还是别的什么?
  • 如果我不够清楚,我很抱歉。假设我有以下课程:@Entity public class Student { @Id private Integer id; @Column(length = 50) private String name; ... }每当我需要插入一个新学生时,hibernate/jpa/jTDS会生成以下语句:@declare @p1 int, declare @p2 varchar(8000); insert into Student (id, name) values (@p1, @p2);我的问题是hibernate/jtds不尊重我的长度= 50 @Column 注释。对于 varchar 列,长度始终为 8000。这是预期的行为吗?

标签: hibernate jpa jtds


【解决方案1】:

我意识到这是一个老问题,但最近我自己也遇到了这个问题,我想我会有所启发。

这似乎是在 jtds 驱动程序中故意的。

如果您查看 TdsData.java,您会在此代码块中看到这种情况:

} else {
    if (pi.isUnicode && len <= MS_LONGVAR_MAX / 2) {
        pi.tdsType = XSYBNVARCHAR;
        pi.sqlType = "nvarchar(4000)";
    } else if (!pi.isUnicode && len <= MS_LONGVAR_MAX) {
        CharsetInfo csi = connection.getCharsetInfo();
        try {
            if (len > 0 && csi.isWideChars() &&
            pi.getBytes(csi.getCharset()).length > MS_LONGVAR_MAX) {
                pi.tdsType = SYBTEXT;
                pi.sqlType = "text";
            } else {
                pi.tdsType = XSYBVARCHAR;
                pi.sqlType = "varchar(8000)";
            }

【讨论】: