с Hibernate и SQL сервером, я сталкиваюсь с проблемой, когда я хочу обновить объект с именем Client . У объекта Client есть поля аудита, такие как имя текущего пользователя, который создает / обновляет его, и время, когда эти операции происходят. Проблема здесь в том, что при обновлении выдается java. sql .SQLException , под журналом для получения дополнительных сведений:
Причина: java. sql .SQLException: Невозможно вставить значение NULL в столбец «IS_SUPPRIMER», таблица «IJSS_DB.dbo.TF_CODE_PA IE»; столбец не допускает значений NULL. ОБНОВЛЕНИЕ не удается. в net .sourceforge.jtds.jdb c .SQLDiagnosti c .addDiagnosti c (SQLDiagnosti c. java: 368) ~ [jtds-1.2.4.jar: 1.2.4] в net .sourceforge.jtds.jdb c .TdsCore.tdsErrorToken (TdsCore. java: 2820) ~ [jtds-1.2.4.jar: 1.2.4] в net .sourceforge.jtds.jdb c .TdsCore.nextToken (TdsCore. java: 2258) ~ [jtds-1.2.4.jar: 1.2.4] в net .sourceforge.jtds.jdb c .TdsCore.getMoreResults (TdsCore. java: 632) ~ [jtds-1.2.4.jar: 1.2.4] в net .sourceforge.jtds.jdb c .JtdsStatement.processResults (JtdsStatement. java: 584) ~ [jtds-1.2 .4.jar: 1.2.4] в net .sourceforge.jtds.jdb c .JtdsStatement.execute SQL (JtdsStatement. java: 546) ~ [jtds-1.2.4.jar: 1.2. 4] в net .sourceforge.jtds.jdb c .JtdsPreparedStatement.executeUpdate (JtdsPreparedStatement. java: 506) ~ [jtds-1.2.4.jar: 1.2.4] в org.hibernate.engine.jdb c .internal.ResultSetReturnImpl.executeUpdate (ResultSetReturnImpl. java: 197) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.persister.entity.AbstractE ntityPersister.update (AbstractEntityPersister. java: 3421) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert (AbstractEntityPersister. java : 3283) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.persister.entity.AbstractEntityPersister.update (AbstractEntityPersister. java: 3695) ~ [hibernate-core- 5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.action.internal.EntityUpdateAction.execute (EntityUpdateAction. java: 149) ~ [hibernate-core-5.4.10.Final.jar: 5.4 .10.Final] в org.hibernate.engine.spi.ActionQueue.executeActions (ActionQueue. java: 604) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate .engine.spi.ActionQueue.lambda $ executeActions $ 1 (ActionQueue. java: 478) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в java .util.LinkedHashMap.forEach (LinkedHashMap. java: 684) ~ [?:?] В org.hibernate.engine.spi.ActionQueue.executeActions (ActionQueue. java: 475) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions (AbstractFlushingEventListener. java: 348) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org. hibernate.event.internal.DefaultFlushEventListener.onFlu sh (DefaultFlushEventListener. java: 40) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.event.service. internal.EventListenerGroupImpl.fireEventOnEachListener (EventListenerGroupImpl. java: 108) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.internal.SessionImpl.doFlu sh (SessionImpl. java: 1344) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.internal.SessionImpl.managedFlu sh (SessionImpl. java: 435) ~ [ hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion (SessionImpl. java: 3221) ~ [hibernate-core-5.4.10.Final.jar : 5.4.10.Final] в org.hibernate.internal.SessionImpl.beforeTransactionCompletion (SessionImpl. java: 2389) ~ [hibe rnate-core-5.4.10.Final.jar: 5.4.10.Final] в org.hibernate.engine.jdb c .internal.JdbcCoordinatorImpl.beforeTransactionCompletion (JdbcCoordinatorImpl. java: 447) ~ [hibernate-core- 5.4.10.Final.jar: 5.4.10. Final] в org.hibernate.resource.transaction.backend.jdb c .internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback (JdbcResourceLocalTransactionCoordinatorImpl. java: 183) ~ [hibernate-core-5.4.10 Final] в org.hibernate.resource.transaction.backend.jdb c .internal.JdbcResourceLocalTransactionCoordinatorImpl.access $ 300 (JdbcResourceLocalTransactionCoordinatorImpl. java: 40) ~ [hibernate-core-5.4.10.Final. .Final] в org.hibernate.resource.transaction.backend.jdb c .internal.JdbcResourceLocalTransactionCoordinatorImpl $ TransactionDriverControlImpl.commit (JdbcResourceLocalTransactionCoordinatorImpl. java: 281) corej .10.Final] в org.hibernate.engine.transaction.internal.TransactionImpl.commit (TransactionImpl. java: 101) ~ [hibernate-core-5.4.10.Final.jar: 5.4.10.Final] в org .springframework.orm.jpa.JpaTransactionManager.doCommit (JpaTransactionManager. java: 534) ~ [spring-orm-5.2.3.RELEASE.jar: 5.2.3.RELEAS E] ... еще 98
Обратите внимание, что столбец IS_SUPPRIMER находится среди полей аудита, которые указывают, удален ли этот столбец или нет (IS_SUPPRIMER = true / deleted, IS_SUPPRIMER = false / не удаляется), в результате мы выполняем логическое удаление, а не физическое удаление.
Что странно, так это то, что объект client , который сопоставлен с таблицей TF_CLIENT , имеет столбец с именем IS_SUPPRIMER со значением по умолчанию, под сценарием:
CREATE TABLE [dbo].[TF_CLIENT] (
[CLT_ID] [bigint] IDENTITY(1,1) NOT NULL,
[CLT_LIBELLE] [nvarchar](50) NOT NULL,
[CLT_DT_OUVERTURE] [date] NOT NULL,
[CLT_DT_FERMETURE] [date],
[CLT_B_ACTIF] [bit] CONSTRAINT DF_TF_CLIENT_B_ACTIF DEFAULT 1 NOT NULL,
[DATE_CREATION] [datetime2](3),
[DATE_MODIFICATION] [datetime2](3),
[DATE_SUPRESSION] [datetime2](3),
[AUTEUR_CREATION] [nvarchar](100),
[AUTEUR_MODIFICATION] [nvarchar](100),
[AUTEUR_SUPRESSION] [nvarchar](100),
[IS_SUPPRIMER] [bit] CONSTRAINT DF_TF_UTILISATEUR_IS_SUPPRIMER DEFAULT 0 NOT NULL
CONSTRAINT UQ_CLT_LIBELLE UNIQUE(CLT_LIBELLE),
CONSTRAINT PK_TF_CLIENT PRIMARY KEY CLUSTERED
(
[CLT_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
, так почему для обновления такого объекта Client потребуется значение IS_SUPPRIMER , который уже имеет значение по умолчанию?
Ниже кода класса аудита:
@Embeddable
@Getter
@Setter
@NoArgsConstructor
public class FieldAuditing implements Serializable {
@Column(name = "DATE_CREATION")
private Instant createdAt;
@Column(name = "DATE_MODIFICATION")
private Instant updatedAt;
@Column(name = "DATE_SUPRESSION")
private Instant deletedAt;
@Column(name = "AUTEUR_CREATION", length = 100)
private String createdBy;
@Column(name = "AUTEUR_MODIFICATION", length = 100)
private String updatedBy;
@Column(name = "AUTEUR_SUPRESSION", length = 100)
private String deletedBy;
@Column(name = "IS_SUPPRIMER")
private Boolean isDeleted = false;
@PrePersist
public void prePersist() {
if (this.isDeleted == null)
setIsDeleted(Boolean.FALSE);
setCreatedAt(Instant.now());
setCreatedBy(LoggedInUser.get());
}
@PreUpdate
public void preUpdate() {
if (this.isDeleted == null)
setIsDeleted(Boolean.FALSE);
setUpdatedAt(Instant.now());
setUpdatedBy(LoggedInUser.get());
}
}
Также Клиент Класс сущности:
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name="TF_CLIENT", schema="dbo")
public class Client implements Serializable {
private static final long serialVersionUID = 8832848102370267801L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator="native")
@GenericGenerator(name = "native", strategy = "native")
@Column(name = "CLT_ID", nullable = false)
private Long id;
@Column(name = "CLT_LIBELLE", nullable = false, length = 50, unique = true)
private String libelle;
@Temporal(TemporalType.DATE)
@Column(name = "CLT_DT_OUVERTURE", nullable = false)
private Date dateOuverture;
@Temporal(TemporalType.DATE)
@Column(name = "CLT_DT_FERMETURE")
private Date dateFermeture;
@Column(name = "CLT_B_ACTIF")
private boolean isActif;
@Embedded
private FieldAuditing fieldAuditing = new FieldAuditing() ;
@JsonIgnore
@OneToMany
@Builder.Default
@JoinColumn(name="CLI_ID")
Set<Etablissement> etablissements = Collections.emptySet();
@JsonIgnore
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name="CLI_ID")
@Builder.Default
@Setter(AccessLevel.NONE)
Set<CodePaie> codePaies = new HashSet<>();
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, mappedBy = "client", orphanRemoval = true)
@Builder.Default
@Setter(AccessLevel.NONE)
Set<ClientAction> clientActions = Sets.newHashSet();
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, mappedBy = "client", orphanRemoval = true)
@Builder.Default
@Setter(AccessLevel.NONE)
Set<ClientEtat> clientEtats = Sets.newHashSet();
public void addClientActions(Set<ClientAction> clientActions) {
clientActions.forEach(clientAction -> clientAction.setClient(this));
this.clientActions.addAll(clientActions);
}
public void addClientEtats(Set<ClientEtat> clientEtats) {
clientEtats.forEach(etat -> etat.setClient(this));
this.clientEtats.addAll(clientEtats);
}
public void addCodePaies(Set<CodePaie> codePaies) {
codePaies.forEach(codePaie -> codePaie.setClient(this));
this.codePaies.addAll(codePaies);
}
public void removeAllCodePaie() {
codePaies.forEach(codePaie -> codePaie.setClient(null));
this.codePaies.clear();
}
}
Наконец, фрагмент кода обновления Клиент entity:
private ClientDto save(ClientDto clientDto, Client client) {
startDateShouldBeBeforeEndDate(clientDto);
hasUniqueCodePaies(clientDto.getCodePaies());
Client clientSaved = clientRepository.save(clientMapper.toEntity(clientDto, client));
clientMapper.addOrRemoveClientActions(clientDto, clientSaved);
clientMapper.addOrRemoveClientEtats(clientDto, clientSaved);
clientRepository.save(clientSaved);
clientDto.setId(clientSaved.getId());
return clientDto;
}
Пожалуйста, взгляните на описание моей проблемы и помогите мне.
Я благодарен за любую помощь.