jpaRepository delete()或deleteById()不起作用,springBoot

u5rb5r59  于 2023-11-17  发布在  Spring
关注(0)|答案(3)|浏览(353)

我需要删除一个Archivo记录,我有下一个案例。我有问题删除使用detele()和deleteById()的代码是什么也不做。
下一个是主代码:

@Override
public RespuestaVo delete(Integer archId) {
    RespuestaVo respuestaVo = new RespuestaVo();

    try {
       if (!validarArchivoDeUsuario(archId)){
            respuestaVo = new RespuestaVo(401, HttpStatus.UNAUTHORIZED, "Acceso a recursos no autorizado.");
            return respuestaVo;
        }
        respuestaVo = new RespuestaVo(201, HttpStatus.OK, "El archivo ha sido eliminado con éxito.");
        iArchivosDao.deleteById(archId);

    } catch (Exception ex) {
        respuestaVo = new RespuestaVo(400, HttpStatus.BAD_REQUEST, "No ha sido posible eliminar el archivo, inténtelo más tarde.");
        Logger.getLogger(LogosEmprendimientosServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
    }
    return respuestaVo;
}

字符串
这段代码使用了一个叫做“validarArchivoDealliario()”的方法,它只是用来验证用户是否收到了归档文件。这个方法做了它必须做的事情。

private boolean validarArchivoDeUsuario(int archId) {
    Personas persona = new Personas();
    persona = jwtProvider.getUserID();
    List<Emprendimientos> emprendimientos;

    emprendimientos =  iEmprendimientosDao.findByPersIdAndEmprEstado(persona, ACTIVO);
    for (Emprendimientos emprendimiento: emprendimientos){
        for (Archivos archivo: emprendimiento.getArchivosCollection()){
            if (archivo.getArchId().equals(Integer.valueOf(archId))){
                return true;
            }
        }
    }
    return false;
}


如果我像现在这样使用代码,它会转到验证,然后转到iArchivosDao.deleteById(archId);行,但它不会做任何事情。
但是如果我在validarArchivoDealliario中注解“for”,并像下一个代码一样硬编码返回true。它也会转到iArchivosDao.deleteById(archId);行,但在这种情况下,它会删除记录:
log:org.hibernate.SQL:delete from archivos where arch_id=?Hibernate:delete from archivos where arch_id=?

private boolean validarArchivoDeUsuario(int archId) {
    Personas persona = new Personas();
    persona = jwtProvider.getUserID();
    List<Emprendimientos> emprendimientos;

    emprendimientos =  iEmprendimientosDao.findByPersIdAndEmprEstado(persona, ACTIVO);
    /*for (Emprendimientos emprendimiento: emprendimientos){
        for (Archivos archivo: emprendimiento.getArchivosCollection()){
            if (archivo.getArchId().equals(Integer.valueOf(archId))){
                return true;
            }
        }
    }*/
    return true;
}


看起来像一些在这里影响删除.我尝试设置emprendimientos,archivo,emprendimiento为null之前返回true,但没有工作
Emprendimientos.java网站...

@OneToMany(cascade = CascadeType.ALL, mappedBy = "emprId")
private Collection<Archivos> archivosCollection;


...
Archivos.java网站...

@Entity
@Table(name = "ARCHIVOS")
@Data
public class Archivos {
...

@JsonBackReference("emprId-Archivo")
@JoinColumn(name = "EMPR_ID", referencedColumnName = "EMPR_ID")
@ManyToOne(optional = false)
priva


te Emprendimientos emprId;
...
谢谢你的健康!

0wi1tuuw

0wi1tuuw1#

看起来这个问题可能与Sping Boot 应用程序中JPA实体和关联关系的Map方式有关。当您在validarArchivoDealliario方法中取消注解for循环时,可能会加载关联的实体和关系,并且删除操作按预期工作。
尝试将@ transmitting注解应用到delete方法中

@Transactional
public RespuestaVo delete(Integer archId) {
    RespuestaVo respuestaVo = new RespuestaVo();

    try {
        // ... Add your existing code ...

        respuestaVo = new RespuestaVo(201, HttpStatus.OK, "El archivo ha sido eliminado con éxito.");
        iArchivosDao.deleteById(archId);

    } catch (Exception ex) {
        // ... your existing error handling ...
    }
    return respuestaVo;
}

字符串

niknxzdl

niknxzdl2#

对我来说,它看起来像,for循环无法找到记录,也无法删除它。请尝试以下操作:

for (Emprendimientos emprendimiento: emprendimientos) {
    for (Archivos archivo: emprendimiento.getArchivosCollection()) {
        if (archivo.getArchId().equals(Integer.valueOf(archId))) {
            // Check if the record exists
            if (iArchivosDao.findById(archId).isPresent()) {
                // Delete the record
                iArchivosDao.deleteById(archId);
                return true;
            } else {
                // The record does not exist
                return false;
            }
        }
    }
}

字符串
不要忘记**@ translation**注解,因为您正在修改数据库。

z9gpfhce

z9gpfhce3#

问题在于archivosCollectionMap上的级联选项,特别是级联PERSIST(包含在CascadeType.ALL中)。您正在删除Archivos的示例,但在同一个持久化单元中保留了一个仍然引用该示例的Emprendimientos示例。JPA将处理您的删除请求,但在检查托管的Emprendimientos示例时,JPA将找到相同的引用,并需要将其持久化回去,撤消删除操作。
在删除之前,你应该先删除this和任何其他对此Archivos的引用。如果你不这样做,你可能会在奇怪的时候发现类似的行为,这样做会给予你的应用程序一个机会和位置,在以后实现缓存时,把回调放到清除缓存中。
您已经有了一个解决方案-通过直接调用本机查询,您将直接向数据库强制执行delete语句。尽管如此,JPA仍然会相信它在该高速缓存中的Archivos存在,并且不会尝试重新插入它-无论如何,现在是这样。您需要确保在提交后清除Emprendimientos的任何缓存示例并从数据库中重新读取,否则您可能会重新读取过时的数据。稍后插入。
或者,您可以从关系中删除cascadeType.PERSIST:

@OneToMany(cascade = CascadeType.DELETE, mappedBy = "emprId")
private Collection<Archivos> archivosCollection;

字符串
只在你确定必须使用级联操作的地方使用级联操作--在大多数情况下,手动创建一个archivosCollection.forEach(arch -> em.persist(arch));要比不使用级联操作容易得多。
第三个选项,我在大多数情况下都推荐的选项,是维护双向关系。由于要删除Archivos,因此应该清除对它的任何引用。有时出于性能原因,不这样做;默认的方法可能是调用

if (null != archivos.emprId) {
  archivos.emprId.archivosCollection.remove(archivos);
}


如果所有内容都还没有加载,可能会强制执行一系列SQL查询。这可以通过使用isLoaded检查来检查关系是否已经加载来调节:

if (null != archivos.emprId) {
  if (Persistence.getPersistenceUtil().isLoaded(archivos.emprId, "archivosCollection") ) {
    archivos.emprId.archivosCollection.remove(archivos);
  }
}

相关问题