【问题标题】:How to save only changed columns in JPA spring-boot [duplicate]如何在JPA spring-boot中仅保存更改的列[重复]
【发布时间】:2017-09-12 11:02:58
【问题描述】:

这与重复的链接问题完全无关!

我的问题是 JPA 试图保存所有字段,即使它没有更改它们,这对我来说在 db2 上破坏了一些东西。

实体:

@Data  // Auto getter and setters by lombok
@Entity
@IdClass(TkmstpId.class)
@Table(name="TKMSTP")
public class Tkmstp implements Serializable { 
    // DMD column: Tkslsk: decimal(2)
    @Id
    @Column(name="TKSLSK")
    private Long slskNr;
    // DMD column: Tkknnr: decimal(7)
    @Id
    @Column(name="TKKNNR")
    private Long kundenr;
    // DMD column: Tknr: decimal(7)
    @Id
    @Column(name="TKNR")
    private Long tankNummer;
    // DMD column: Tkstat: decimal(1)
    @Column(name = "TKEVOL")
    private Long estAarsForbrug;
    @Column(name = "TKGDK")
    private Long gKode;
    @Column(name = "TKUDSSKY")
    private String udskrivKortJn;
    @Column(name="TKLV5DAT")
    private java.sql.Date leveringsDato_tklv5dat;
    // DMD column: Tkudssky: char(1)

}

处理:

TkmstpId id = new TkmstpId();
                id.setKundenr(Long.parseLong(customer.getAccountNumber()));
                id.setSlskNr(1L);
                id.setTankNummer(customer.getContainerId());
                Tkmstp container = tkmstpRepository.getOne(id);
                if (container != null) {
                    boolean changed = false;
                    if (container.getEstAarsForbrug() == null || container.getEstAarsForbrug() == 0L) {
                        changed = setContainerEstimatedValues(container, customer);
                    } else if (container.getGKode() != 5L && container.getGKode() != 6L) {
                        changed = setContainerEstimatedValues(container, customer);
                    }
                    if (changed) {
                        tkmstpRepository.save(container);
                        System.out.println("updated container info on: customer: " + id.getKundenr() + " and container: " + id.getTankNummer());
                    }
                }

SQL 生成:

Hibernate: update tkmstp set tklv5dat=?, tkudssky=?, tkevol=?, tkgdk=? where tkknnr=? and tkslsk=? and tknr=?

我想要的 SQL(没有 tklv5dat)
更新 tkmstp 设置 tkudssky=?, tkevol=?, tkgdk=? tkknnr=?和 tkslsk=?和 tknr​​=?

错误:
java.sql.SQLException: [SQL0407] 列或变量 TKLV5DAT 中不允许空值。

提前谢谢大家...

Application.properties jpa 设置:

 spring.jpa.database-platform=org.hibernate.dialect.DB2Dialect
 spring.jpa.hibernate.ddl-auto = false spring.jpa.show-sql=true 
 spring.datasource.driver-class-name=com.ibm.as400.access.AS400JDBCDriver

【问题讨论】:

  • 更新前 TKLV5DAT 中有什么?它是 null 还是包含一个值?
  • @PaulNUK 它是空的,我知道很奇怪,但那是因为 JPA 以前没有用于此,他们可以在限制后保存值。
  • 您不想更新这些字段?或者你想有时更新它们,有时不更新?
  • @BrankoIlic 我想更新它们几次,这就是为什么@Modifying@Query 看起来很糟糕。
  • 执行此操作的是您的 JPA 提供者,而不是“JPA”。我想知道那是哪个 JPA 提供商?

标签: hibernate jpa spring-boot spring-data-jpa


【解决方案1】:

imO 这是不允许的,要么字段是瞬态的并且根本不保存,要么如果您使用 ORM 层,则必须将对象与其所有字段一起保存以确保对象的完整性得到保证。所以我认为实现你想要的唯一方法是使用显式更新语句。

em.createQuery(
   "update tkmstp t 
       set t.tkudssky=:tkudssky, t.tkevol=:tkevol, t.tkgdk=:tkgdk 
       where t.tkknnr=:tkknnr and t.tkslsk=:tkslsk and t.tknr=:tknr")
   .setParameter(":tkudssky",container.tkudssky)
   .setParameter(":tkevol",container.tkevol)
   .setParameter(":tkgdk",container.tkgdk)
   .setParameter(":tkknnr",container.tkknnr)
   .setParameter(":tkslsk",container.tkslsk)
   .setParameter(":tkudssky",container.tkudssky)
   .executeUpdate();

另一种可能性是使用 DBMS-Means 直接使用一个更新将 TKLV5DAT 设置为正确的默认值。积极的副作用是,DBMS-Checks 和 JPA-Checks 可能是相同的。

【讨论】:

    【解决方案2】:

    加载时列值看起来为空,因此侵入性最小的修复方法是使数据库上的列可以为空。

    【讨论】:

      猜你喜欢
      • 2021-06-22
      • 2020-02-03
      • 2018-10-26
      • 2019-09-24
      • 2019-03-12
      • 2017-12-11
      • 2019-10-09
      • 2022-01-17
      • 2021-01-28
      相关资源
      最近更新 更多