Olá galera, não costumo postar a não ser que fique encalhado em algo por um tempo relativamente grande rsrs basicamente não consigo inserir/alterar/deletar ao mesmo tempo meu objeto Foto! :lol: segue o resumo:
Tenho a classe Album 1-N Foto, eu persisto o objeto foto primeiro(realizo um upload assíncrono) e ao terminar salvo as fotos em uma List no objeto Album(onde, as fotos já armazenadas, apenas fazem um update com a FK do Album), estou fazendo um mapeamento bidirecional, o problema ocorre quando defino o cascadeType como ALL, ele insere e altera porém não deleta causando uma [color=red]org.hibernate.ObjectDeletedException[/color](a stacktrace está no fim do código), se defino o cascadeType como MERGE, ele altera e deleta, mas NÃO insere, os registros de fotos não são atualizados com a FK do Album!
Em minhas pesquisas encontrei algumas possíveis soluções como:
*Utilizar CascadeType.DELETE_ORPHAN
*remover suas relações nos parents objects
Também já tentei todas as combinações possíveis de cascadeType além do ALL, para ver se alguma dava certo(Ex: PERSIST+MERGE+REMOVE[ou DELETE]) sem sucesso, é a primeira vez que tento o relacionamento OneToMany
Acredito muito que meu erro seja exatamente esse, não estou limpando a foto em seus devidos lugares porém, removo-a do objeto album, não sei onde mais posso removê-la, se não for isso devo estar mapeando errado, se puderem me dar uma luz agradeço :lol:
Segue meu mapeamento e o método assíncrono de apagar as fotos que estou utilizando:
[color=red]Foto.java[/color]
public class Foto extends ValidatorForm{
private static final long serialVersionUID = 2345678;
private long id;
private String arquivo;
private FormFile file = null;
private Album album;
public Foto() {
}
public Foto(String arquivo) {
this.arquivo = arquivo;
}
@Id
@GeneratedValue
@Column(name="id")
public long getId() {
return id;
}
@Column(name = "strArquivo", nullable = false)
public String getArquivo() {
return arquivo;
}
public void setArquivo(String arquivo) {
this.arquivo = arquivo;
}
@Transient
public FormFile getFile() {
return file;
}
public void setFile(FormFile file) {
this.file = file;
String caminho = Info.getProjectPath("/")+"arquivos";
try {
Upload.enviaArquivo(caminho, this);
} catch (IOException e) {
e.printStackTrace();
}
}
@ManyToOne
@PrimaryKeyJoinColumn
public Album getAlbum() {
return album;
}
public void setAlbum(Album album) {
this.album = album;
}
@Override
public String toString() {
return getId() + " | " + arquivo;
}
}
[color=red]Album.java[/color]
public class Album extends ValidatorForm{
private static final long serialVersionUID = -8932529389009134248L;
private long id;
private String nome;
private List<Foto> fotos;
public Album() {
}
public Album(List<Foto> fotos) {
this.fotos = fotos;
createName();
}
@Id
@GeneratedValue
@Column(name="id")
public long getId() {
return id;
}
@Column(name = "strNome", nullable = false)
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@OneToMany (targetEntity=Foto.class, mappedBy="album", fetch=FetchType.EAGER)
@Cascade({org.hibernate.annotations.CascadeType.ALL})
public List<Foto> getFotos() {
return fotos;
}
public void setFotos(List<Foto> fotos) {
this.fotos = fotos;
if (nome == null || nome.equals("")) {
createName();
}
}
//REMOVE FOTO
public boolean removeFoto(Foto foto){
return removeFoto(foto.getId());
}
public boolean removeFoto(long id){
if (fotos != null) {
for (int i = 0; i < fotos.size(); i++) {
if (fotos.get(i).getId() == id) {
fotos.remove(i);
return true;
}
}
}
return false;
}
// VERIFICA SE FOTO EXISTE
public boolean isFotoExiste(Foto foto){
return isFotoExiste(foto.getId());
}
public boolean isFotoExiste(long id){
if (fotos != null) {
for (int i = 0; i < fotos.size(); i++) {
if (fotos.get(i).getId() == id) {
return true;
}
}
}
return false;
}
@Override
public String toString() {
return getId()+ " | " + nome + " | " + fotos;
}
private void createName(){
this.nome = "album_"+new Timestamp().getDate().getTime();
}
}
[color=red]FotoAction.java[/color]
public class FotoAction extends DispatchAction {
private static final FotoDAO fotoDAO = FotoDAO.getInstance();
public ActionForward deleta(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
//DELETA BEAN PELO ID DA QUERYSTRING
long id = Long.parseLong(request.getParameter("id"));
if (id != 0) {
Foto fotoDeleta = fotoDAO.get(id);
if (fotoDeleta.getAlbum() != null && fotoDeleta.getAlbum().isFotoExiste(fotoDeleta)) {
fotoDeleta.getAlbum().removeFoto(fotoDeleta);
fotoDeleta.setAlbum(null);
}
fotoDAO.apagar(id);
}
return mapping.findForward(null);
}
}
[color=red]Segue a stacktrace:[/color]
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.es.napegada.admin.album.foto.Foto#18]
at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:1230)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:188)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.es.utils.hibernate.GenericDAO.apagar(GenericDAO.java:144)
at com.es.napegada.admin.album.foto.FotoAction.deleta(FotoAction.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:270)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:187)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:279)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Agradeço antecipadamente e assim que eu descobrir uma solução para a mesma posto aqui