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(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)
totext
, иначе ничего появляется произойдет.