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

Одно из моих объектов 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.

Затем я пытаюсь выполнить raw INSERT из командной строки MySQL, и он работает! Я могу вставить длинные заметки в этом поле!

Наконец, я DROP моя локальная/промежуточная схема DB и измените hibernate.hbm2ddl.auto в persistence.xml на create, и она работает.

По-прежнему ли JPA считает, что это a VARCHAR? Есть ли у него какой-то кеш или какое-то место, где он хранит информацию о схеме?

Я не могу отказаться от своего производства db, очевидно. Итак, что я могу сделать для reset или изменить тип столбца?

Я использую JBossAS7 JPA 2-Hibernate.

Ответ 1

НИЧЕГО! Я закончил с: - резервная копия - hbm2ddl = > CREATE-DROP - hbm2ddl = > ОБНОВЛЕНИЕ - Восстановление базы данных

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

Ответ 2

В окончательной книге Hibernate "Сохранение Java с Hibernate" упоминается об обновлении для hibernate.hbm2ddl.auto (жирные шрифты мои)

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

Также документы Hibernate предлагают тот же здесь

Средство 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.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

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

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

Однако, если я использую update и вместо для изменения свойства, я добавляю другое местоположение свойства, а затем исправляет sql снова генерируется

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

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

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

Ответ 3

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

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

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

Причина

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

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

Симптомы

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

Решение

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

ALTER TABLE piece_aud MODIFY notes LONGTEXT;

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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

alter table your_table modify column your_column text

и вуаля!

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

Ответ 9

В Spring/JPA/Hibernate/Postgres,

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

Работает как очарование для меня!

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

Ответ 10

@Column( length = 100000 )
private String text;

Это работает, но вы должны удалить таблицу ! Потому что в этом случае hibernate не обновляет таблицу. Таким образом, вы должны заставить Hibernate воссоздать таблицу, и это работает!