我需要删除一个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;
...
谢谢你的健康!
3条答案
按热度按时间0wi1tuuw1#
看起来这个问题可能与Sping Boot 应用程序中JPA实体和关联关系的Map方式有关。当您在validarArchivoDealliario方法中取消注解for循环时,可能会加载关联的实体和关系,并且删除操作按预期工作。
尝试将@ transmitting注解应用到delete方法中
字符串
niknxzdl2#
对我来说,它看起来像,for循环无法找到记录,也无法删除它。请尝试以下操作:
字符串
不要忘记**@ translation**注解,因为您正在修改数据库。
z9gpfhce3#
问题在于archivosCollectionMap上的级联选项,特别是级联PERSIST(包含在CascadeType.ALL中)。您正在删除Archivos的示例,但在同一个持久化单元中保留了一个仍然引用该示例的Emprendimientos示例。JPA将处理您的删除请求,但在检查托管的Emprendimientos示例时,JPA将找到相同的引用,并需要将其持久化回去,撤消删除操作。
在删除之前,你应该先删除this和任何其他对此Archivos的引用。如果你不这样做,你可能会在奇怪的时候发现类似的行为,这样做会给予你的应用程序一个机会和位置,在以后实现缓存时,把回调放到清除缓存中。
您已经有了一个解决方案-通过直接调用本机查询,您将直接向数据库强制执行delete语句。尽管如此,JPA仍然会相信它在该高速缓存中的Archivos存在,并且不会尝试重新插入它-无论如何,现在是这样。您需要确保在提交后清除Emprendimientos的任何缓存示例并从数据库中重新读取,否则您可能会重新读取过时的数据。稍后插入。
或者,您可以从关系中删除cascadeType.PERSIST:
字符串
只在你确定必须使用级联操作的地方使用级联操作--在大多数情况下,手动创建一个archivosCollection.forEach(arch -> em.persist(arch));要比不使用级联操作容易得多。
第三个选项,我在大多数情况下都推荐的选项,是维护双向关系。由于要删除Archivos,因此应该清除对它的任何引用。有时出于性能原因,不这样做;默认的方法可能是调用
型
如果所有内容都还没有加载,可能会强制执行一系列SQL查询。这可以通过使用isLoaded检查来检查关系是否已经加载来调节:
型