JPA:“数据太长,列”不会改变(JPA: “Data too long for column” d

2019-07-31 13:13发布

我的一个实体的Machinery得到了一个String名为属性notes 。 JPA 2 Hibernate的生成模式对我来说,在我的情况下,RDBMS是一个MySQL。

notes作为一个创建VARCHAR(255)柱,这是正确的。

用户开始创建记录和所有完美的作品,但后来一些用户得到了臭名昭著的Data too long for column "notes"的错误。

那场有没有足够的空间供用户机器笔记! 好的,没问题。 让我们改变的模式!

所以,我打开我的实体类和改变我的属性:

@Column(length=1000000)
@Lob
private String notes;

顺便说一句,我persistence.xml声明:

<property name="hibernate.hbm2ddl.auto" value="update" />

重新启动应用程序后,我很高兴,Hibernate是为了改变我的notes栏的LONGTEXT (这是足以让我)。

所以我第一次尝试使用我的应用程序创建一个新的“长指出”记录,我仍然是错误的“数据太长”虽然是一个LONGTEXT现在。

于是,我尝试做一个原始INSERT从MySQL命令行和它的作品! 我可以在字段中插入长音符!

最后,我DROP我的本地/分期DB模式改变hibernate.hbm2ddl.autopersistence.xml ,以create和它的作品。

JPA是否仍然认为这是一个VARCHAR ? 是否有某种缓存或一些其存储架构的信息的地方吗?

我无法将我的生产分贝,效果显着。 所以,我能做些什么来重置或更改列的类型?

我使用JPA JBossAS7 2休眠。

Answer 1:

该权威Hibernate的书“Java持久与Hibernate”提到了hibernate.hbm2ddl.auto(加粗是我的)这对更新

此配置属性,更新的附加选项,可以在开发过程中是有用的:它使内置SchemaUpdate工具对,它可以使模式演变更加容易。 如果打开,Hibernate在启动时读取JDBC数据库的元数据和旧模式与当前的映射元数据进行比较创建新表和约束。 需要注意的是此功能依赖于JDBC驱动程序,很多司机都缺乏在一个地区提供的元数据的质量 。 在实践中,这一功能因此更令人兴奋的和有用的比它听起来是。

Hibernate也文档建议同样在这里

SchemaUpdate工具对更新与“增量”的转变现有的模式。 该SchemaUpdate工具依赖于JDBC的metadata API和,因此,不会对所有的JDBC驱动程序。

我试图复制你的使用情况,并发现它令人惊讶的,我也有这个问题。

我有这样一个用户实体

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table( name = "usr" )

public class User {
  @Id
  @GeneratedValue
  private Long id;

  @Column( length = 40, unique = true )
  private String name;

  @Lob
  @Column( length = 100000 )
  private String text;

  public long getId() {
    return id;
  }

  public void setName( String name ) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public String getText() {
    return text;
  }

  public void setText( String text ) {
    this.text = text;
  }

}

和我的坚持XML是这样的

<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.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="jpatest" transaction-type="RESOURCE_LOCAL">
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value="root"/>
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpadatabase"/>
            <property name="hibernate.show-sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

如果我改变hibernate.hbm2ddl.auto的价值创造和实体的文本属性更改为这

.....

  @Column( length = 255 )
  private String text;
......

该模式发生器产生在启动时下面的SQL

DEBUG SchemaExport:415 - drop table if exists usr
DEBUG SchemaExport:415 - create table usr (id bigint not null auto_increment, name varchar(40) unique, text varchar(255), primary key (id)) ENGINE=InnoDB
INFO SchemaExport:281 - schema export complete

现在再次改变实体的财产

.....
@Lob
@Column( length = 100000 )
private String text;
.......

现在产生以下正确的SQL

DEBUG SchemaExport:415 - drop table if exists usr
DEBUG SchemaExport:415 - create table usr (id bigint not null auto_increment, name varchar(40) unique, text longtext, primary key (id)) ENGINE=InnoDB
INFO SchemaExport:281 - schema export complete

到现在为止还挺好。

的事实,我已经更新从varchar(255)的文本列现在,如果我改变的价值hibernate.hbm2ddl.auto更新和重复实体上述变化以相同的顺序,不产生更新的列SQL inspite到LONGTEXT

 INFO TableMetadata:65 - table found: jpadatabase.usr
 INFO TableMetadata:66 - columns: [id, text, name]
 INFO TableMetadata:68 - foreign keys: []
 INFO TableMetadata:69 - indexes: [name, primary]
 DEBUG DefaultIdentifierGeneratorFactory:90 - Setting dialect  [org.hibernate.dialect.MySQL5InnoDBDialect]
 INFO SchemaUpdate:217 - schema update complete

但是,如果我使用的更新和而不是通过修改属性,我添加了另一个属性位置,然后正确的SQL再次产生

DEBUG SchemaUpdate:203 - alter table usr add column location varchar(255)
INFO SchemaUpdate:217 - schema update complete

因此,在本质上是创建(这第一滴表,然后重新创建)工作正常但是更新不如果在属性元数据的修改。

对我来说,它看起来像对增量更新的驱动程序支持的问题是在这里打球。 也直观地如果我想这一点,那么就没有任何意义给予支持更新列的数据类型。 如果修改列数据类型是较早的数据类型的缩小版本,会出现什么情况的现有数据。



Answer 2:

我只是有这个问题,之后阅读本我找到了答案,是非常合乎逻辑的,如果你仔细想想,与envers经审计的表有关。

如何重现

  • 您正在使用休眠envers
  • 你改变一个列的类型代码添加注释@Lob。

原因

休眠只更新原始表,而不是审计之一,这是休眠的功能:

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

症状

“太长数据的列‘X’” MysqlDataTruncation引发异常与臭名昭著。

手动更新审计表的类型。 例:

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

这是非常棘手的,因为异常只能说列的名称,而不是表的名称!!,这就是为什么删除并重新创建模式也适用,导致经审计表再生。



Answer 3:

我有同样的问题INSTER陈述工作数据库完全直接的,而是通过休眠这样做没有工作,产生的数据截断:数据太长,列。 一切工作的时候就是hbm2ddl改为创建降。

但我真正的问题是由于我使用使用Hibernate的建立审计功能,审计表。 主表是正确更新为增加的大小而不是审计表,以便写审核表的所有变化导致此数据截断误差。 只需手动更新在审计表中的列,以正确的大小和一切工作正常。



Answer 4:

我也有同样的情况,并且下面一个是为我工作顺利

@Column(name="your_column_name",columnDefinition="LONGTEXT")
private String notes;

我知道有人问长回来,但它仍然可能是帮助别人。 :)



Answer 5:

没有! 我结束了: - DB备份 - 就是hbm2ddl => CREATE-DROP - 就是hbm2ddl =>更新 - DB恢复

疯! :(



Answer 6:

我觉得这个问题解决了@Column(columnDefinition="LONGVARCHAR")



Answer 7:

至于我,我排除了下列属性和问题消失

<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>


Answer 8:

很烦人的问题,虽然。 相反,备份整个数据库,改变的hibernate.hbm2ddl.auto ,方言面向ALTER TABLE SQL的都可以使用。 例如; 为MySQL只需更新与列类型

alter table your_table modify column your_column text

瞧!

PS:不要忘记更新审计表!



Answer 9:

在Spring / JPA /休眠/ Postgres的,

@Type(type="org.hibernate.type.StringClobType")
String message;

作品对我来说就像魅力!

重要提示 :在数据库中的字段类型不会自动更新我的,所以我需要为允许Hibernate来重新创建表,或手动更改从类型varchar(255)text ,否则好像没有任何反应。



Answer 10:

@Column( length = 100000 )
private String text;

工作 ,但你必须要删除 ! 因为Hibernate没有在这种情况下更新表。 所以,你必须强制Hibernate 重新创建表和它的作品!



文章来源: JPA: “Data too long for column” does not change