Ответ 1
НИЧЕГО! Я закончил с: - резервная копия - hbm2ddl = > CREATE-DROP - hbm2ddl = > ОБНОВЛЕНИЕ - Восстановление базы данных
Сумасшедшие!: (
Одно из моих объектов 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.
НИЧЕГО! Я закончил с: - резервная копия - hbm2ddl = > CREATE-DROP - hbm2ddl = > ОБНОВЛЕНИЕ - Восстановление базы данных
Сумасшедшие!: (
В окончательной книге 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
Таким образом, по существу создание (которое сначала отбрасывает таблицу, а затем воссоздает) работает правильно, однако обновление не происходит, если есть модификация в метаданных свойств.
Мне кажется, что здесь стоит играть роль поддержки драйверов для инкрементных обновлений. Также интуитивно Если я думаю об этом, тогда нет смысла оказывать поддержку для обновления типа столбцов. Что произойдет с существующими данными, если измененный тип данных столбца - это уменьшенная версия более раннего типа данных.
У меня просто была эта проблема, после того как я прочитал это, я нашел ответ, очень логично, если вы думаете об этом, связан с проверенными таблицами envers.
Hibernate обновляет только исходную таблицу, а не проверенную, это то, что делает спящий режим:
ALTER TABLE piece_aud MODIFY notes LONGTEXT;
Исключение MysqlDataTruncation возникает с печально известными "Данные слишком длинны для столбца" x ".
Вручную обновить тип проверяемой таблицы. Пример:
ALTER TABLE piece_aud MODIFY notes LONGTEXT;
Это было очень сложно, потому что в исключении указывается только имя столбца, а не имя таблицы!!, что также заставляет и восстанавливать и восстанавливать схему, заставляя проверенные таблицы регенерироваться.
У меня была та же проблема, что и инструкция INSTER работала совершенно напрямую в базе данных, но выполнение ее через Hibernate не работало и не производилось. Усечение данных: слишком большие данные для столбца. Все работало, когда hbm2ddl был изменен на создание-drop.
Но моя реальная проблема заключалась в том, что я использовал таблицы аудита с использованием сборки Hibernate в функции Audit. Основная таблица была правильно обновлена до увеличенного размера, но не таблицы аудита, поэтому все изменения, которые были записаны в таблицу Audit, вызвали эту ошибку обрыва данных. Просто вручную обновляйте столбец таблицы аудита до нужного размера, и все работает нормально.
У меня тоже был такой же сценарий, и ниже одного у меня работает плавно
@Column(name="your_column_name",columnDefinition="LONGTEXT")
private String notes;
Я знаю, что это было задано давно, но все же это может помочь кому-то. :)
Я думаю, что это решает проблему
@Column(columnDefinition="LONGVARCHAR")
Что касается меня, я исключаю следующие свойства и проблема исчезает
<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: Не забывайте обновлять таблицы аудита!
В Spring/JPA/Hibernate/Postgres,
@Type(type="org.hibernate.type.StringClobType")
String message;
Работает как очарование для меня!
Важное примечание. Тип столбца в базе данных не автообновляется для меня, поэтому мне нужно либо разрешить Hibernate воссоздать таблицу, либо вручную изменить тип с
varchar(255)
наtext
, иначе ничего не произойдет.
@Column( length = 100000 )
private String text;
Это работает, но вы должны удалить таблицу ! Потому что в этом случае hibernate не обновляет таблицу. Таким образом, вы должны заставить Hibernate воссоздать таблицу, и это работает!