JPA Аннотация @Column (inserttable = false) игнорируется, почему? - PullRequest
0 голосов
/ 13 ноября 2018

Я хочу, чтобы одно из полей игнорировалось при вызове метода save(). Поле будет автоматически заполнено базой данных и возвращено. Его следует рассматривать как поле только для чтения.

Меня беспокоит поле private Timestamp ts;:

@Entity
@Table(name = "time_series", schema = "ms")
@IdClass(Reading.class)
public class Reading implements Serializable {

   private static final long serialVersionUID = 1L;

   @Id
   @Column(name = "name", nullable = false)
   private String sensorName;

   @Id
   @Column(name = "ts", insertable = false, updatable = false)
   private Timestamp ts;

   @Column(name = "reading")
   private Double value;
   ...

Как видите, я использую insertable = false, updatable = false внутри аннотации @Column, поэтому я ожидаю, что ts игнорируется при формировании фактического SQL за занавесом.

@Override
@Transactional(readOnly = false)
public Reading save(Reading r) {        
    return readingRepository.save(r);
}

ReadingRepository в основном расширен * Spring 101 * CrudRepository , который имеет метод save(...).

Когда я сохраняю Чтение объекта с ts=null Я получаю сообщение об ошибке от Postgres:

ОШИБКА: нулевое значение в столбце "ts" нарушает ненулевое ограничение

потому что Spring Data на самом деле не игнорировал ts на основе поля , что я вижу из журнала :

insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)

Ясно, что я хочу, чтобы запрос был без ts , например:

insert into ms.time_series (name, reading) values ('sensor1', 10.0)

Почему поле не игнорируется?

Теперь, если вы спросите меня, в порядке ли моя схема базы данных, я отвечу да. Когда я набираю SQL-запрос в консоли без TS все нормально. Я даже попробовал аннотации @Generated и @GeneratedValue. Имя и ts оба формируют первичный ключ для таблицы, однако результат будет одинаковым, если я сделаю только один из них PK или добавлю дополнительный столбец суррогатного идентификатора , Тот же результат ...

Я что-то пропускаю или, может быть, есть ошибка в платформе Spring ?? Я использую Spring 5.1.2 и SpringData 2.1.2

Примечание. Если я использую аннотацию @Transient, которая сохраняет запрос на вставку правильно, но поле полностью игнорируется даже при чтении / извлечении.

Большое спасибо за любую помощь в этом!

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Как вы говорите

Я получаю сообщение об ошибке от Postgres

Если вы проверите документы , в нем говорится:

Технически, ограничение первичного ключа - это просто комбинация уникального ограничения и ограничения, не равного NULL.

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

Таким образом, если ts является частью вашего первичного ключа в базе данных (как указывает @Id), просто невозможно вставить нулевые значения в этот столбец.

IMO Hibernate / Spring не имеет никакого отношения к этому как

insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)

должно быть эквивалентно

insert into ms.time_series (name, reading) values ('sensor1', 10.0)
0 голосов
/ 13 ноября 2018

Попробуйте использовать GenericGenerator и GeneratedValue в своем коде.

Добавьте необходимую аннотацию и присвойте значения всем остальным членам класса Reading, кроме ts.

Вот несколько примеров .

...