JPA: "данные слишком длинные для столбца" не изменяется

одна из моих сущностей Machinery получил String свойство notes. JPA 2-Hibernate генерирует схему для меня, в моем случае СУБД-это 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 изменяет мой

9 ответов


окончательная книга Hibernate "Java persistence with Hibernate" упоминает об этом обновление значение спящий режим.hbm2ddl.авто (жирным шрифтом-мои)

дополнительная опция для этого свойства конфигурации, update, может быть полезно во время разработки: он включает встроенный инструмент SchemaUpdate, что может облегчить эволюцию схемы. Если включено, Hibernate читает метаданные базы данных JDBC при запуске и создает новые таблицы и ограничения путем сравнения старой схемы с текущим отображением метаданные. обратите внимание, что эта функция зависит от качества метаданные, предоставляемые драйвером JDBC, область, в которой много драйверов не хватает. На практике эта функция поэтому менее захватывающая и полезнее, чем кажется.

также Hibernate docs предлагают то же самое здесь

инструмент SchemaUpdate обновит существующую схему с помощью "добавочное изменение. SchemaUpdate зависит от метаданных JDBC 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.авто для создания и изменения свойства text объекта на это

.....

  @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

пока все хорошо.

теперь, если я изменю значение hibernate.hbm2ddl.авто для обновления и повторения вышеуказанного изменения в сущности в том же порядке, не создается столбец обновления sql, несмотря на то, что я обновил текстовый столбец из varchar (255) в 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

таким образом, по сути, create (который сначала удаляет таблицу, а затем воссоздает) работает правильно, однако обновление не работает, если есть изменение в метаданных свойств.

мне кажется, что проблема поддержки драйверов для инкрементных обновлений находится на играть здесь. Также интуитивно, если я думаю об этом, то нет смысла давать поддержку для обновления типа данных столбцов. Что произойдет с существующими данными, если измененный тип данных столбца является уменьшенной версией более раннего типа данных.


У меня была такая же проблема с инструкцией INSTER, которая отлично работала с базой данных, но делала это через Hibernate, не работала и производила усечение данных: данные слишком длинные для столбца. Все работало, когда hbm2ddl был изменен на create-drop.

но моя реальная проблема заключалась в том, что я использовал таблицы аудита, используя Hibernate build в функциональности аудита. Основная таблица была правильно обновлена до увеличенного размера, но не таблица аудита, поэтому все изменения, которые были записаны в таблицу аудита вызвал эту ошибку усечения данных. Просто вручную обновить столбец в таблице аудита до нужного размера и все работало нормально.


у меня просто была эта проблема, после прочтения этого я нашел ответ, очень логично, если вы думаете об этом, связано с проверенными таблицами envers.

как воспроизвести

  • вы используете hibernate envers
  • вы изменяете тип столбца в коде, добавляя аннотацию @Lob.

причина

Hibernate обновляет только исходную таблицу, а не проверенную, это то, что hibernate делает:

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

симптомы

исключение MysqlDataTruncation вызывается с печально известными "данными слишком длинными для столбца "x".

решение

вручную обновите тип проверяемой таблицы. Пример:

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

Это было очень сложно, потому что исключение говорит только имя столбца, а не имя таблицы!!, вот почему drop и re-create schema также работают, вызывают регенерацию проверенных таблиц.


ничего! Я закончил с: - Резервное копирование БД - hbm2ddl => создать-падение - hbm2ddl = > обновить - DB restore

сумасшедший! :(


Я думаю, что это решает проблему @Column(columnDefinition="LONGVARCHAR")


У меня тоже был тот же сценарий, и ниже один работает гладко для меня

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

Я знаю, что его попросили давно, но все же это может помочь кому-то. :)


Что касается меня, я исключаю следующие свойства, и проблема уходит

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

довольно раздражающая проблема, хотя. Вместо резервного копирования всей БД и изменения hibernate.hbm2ddl.auto, ориентированный диалект ALTER TABLE SQL можно использовать. Например; для MySQL просто обновите тип столбца с

alter table your_table modify column your_column text

и вуаля!

PS: Не забудьте обновить таблицы аудита!


весной / JPA / спящий режим / Postgres,

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

работает как шарм для меня!

Важное Замечание: тип столбца в базе данных не обновляется автоматически для меня, поэтому мне нужно либо разрешить Hibernate воссоздать таблицу, либо вручную изменить тип с varchar(255) to text, иначе ничего появляется произойдет.