Relacionamento CascadeType

Tenho um relacionamento MAnyToMany, com Setor tem muitos Procedimentos e Procedimento tem muitos Setores.
A minha dúvida é, adiciono na lista os procedimentos ao setor, por enquanto via MySQL, na mão, consigo listar na aplicação e implementei o Edite e excluir, mas quando estou excluindo, por exemplo um procedimento de um Setor que tem por exemplo 4 procedimento, ele esta excluindo todos procedimentos e o Setor junto. Qual CascadeType seria ou alem do cascade tenho que implementar diferente meu excluir?

::: SETOR

@ManyToMany(cascade =  CascadeType.ALL)
@JoinTable(name="setor_proced",
			joinColumns={@JoinColumn(name="procedimento_id")},
			inverseJoinColumns={@JoinColumn(name="setor_id")})
private List<Procedimento> procedimentos = new ArrayList<Procedimento>();

:::PROCEDIMENTO

@ManyToMany(mappedBy="procedimentos", cascade = CascadeType.ALL)
private List<Setor> setores = new ArrayList<Setor>();

aqui no link abaixo tem uma duvida parecida com a sua e algumas soluções possíveis.
https://stackoverflow.com/questions/4935095/jpa-hibernate-many-to-many-cascading

1 curtida

Amigo, isto é um erro classifico de relacionamento em OO, você precisa se perguntar sempre, um setor tem um procedimento ou um procedimento tem um setor, acho que a resposta para seu caso é um setor tem um procedimento, então os procedimentos não precisam conhecer os setores que os possuem e o cascade propaga todas as ações que você implementa aquele objeto.

//um setor tem vários procedimentos
@OneToMany(cascade =  CascadeType.ALL, mappedBy = Setor.class)
private List<Procedimento> procedimentos = new ArrayList<Procedimento>();

//vários procedimentos de um setor
@ManyToOne
private List<Setor> setores = new ArrayList<Setor>();

Assim o jpa vai criar a terceira tabela automaticamente não precisando fazer um joincolumn e também a propagação só será realizada quando você excluir um setor e não mais quando excluir um procedimento. Também você poderá ter um mesmo procedimento em outros setores.

1 curtida

Sim… faz sentido mesmo. E com relação a questão de excluir depois o procedimento, por que, assim terei dois casos: Tenho a tela que lista os procedimento, e se nesta tela eu excluir ele direto, como fica se algum Setor tiver ele em sua lista? E também, se na tela de Setor tenho todos Setores listado, e clico em um setor X e em outra tela listo os procedimentos que tenho nele, se eu excluir aquele procedimento, tenho que criar um metodo especifico para tirar ele da lista do setor X, isso (Sem excluir aquele procedimento do sistema, mas só da lista do X)?

Rafael, quando você tem uma lista distribuída você deve criar triggers para impedir a exclusão no caso de existirem múltiplos usos, mas no código que escrevi para você ao excluir um procedimento qualquer ele sumiria de todos os setores. Fazemos essas listas para evitar cadastros com descrições repetitivas, caso queria registrar procedimentos e depois atribui-los sem nenhum vinculo você precisa criar um cadastro de procedimentos e replicar os mesmos em outra tabela, então ao excluir do cadastro você não afetaria os registros dos setores e vice-versa.

1 curtida

Sim, entendi.
Vou implementar aqui e comento. Muito obrigado.
Assim que der certo, confirmar registro a resposta, pode ser? :+1::slightly_smiling_face::slightly_smiling_face:

1 curtida

Ola, Villagram
o mappedBy = Setor.class gera um erro:
Type mismatch: cannot convert from Class to String

O que pode ser?

Não deveria ser:

 //um setor tem vários procedimentos
@OneToMany(cascade =  CascadeType.ALL, mappedBy = "setores")
private List<Procedimento> procedimentos = new ArrayList<Procedimento>();

//vários procedimentos de um setor
@ManyToOne
private List<Setor> setores = new ArrayList<Setor>();

@Rafael_Blum O mappedBy server para indicar a classe que é “dona” do relacionamento e que vai ter um comportamento de parecido com o de uma super class, essa exceção é gerada por que você está colocando um parâmetro errado, o que deve ser informado é a classe, não uma String…
Coloque o nome da classe seguido de “.class”.
Exemplo: mappedBy = Setor.class

Normalmente eu coloco o nome da classe onde o relacionamento foi mapeado.

Mas eu fiz como falou… :frowning:
Coloquei a classe, mas fica com erro…

E se coloco mudando como String, como pede o erro ficando mappedBy = “setores”
Gera o erro:

   org.hibernate.AnnotationException: @OneToOne or @ManyToOne on 
    br.com.project.model.classes.Procedimento.setores references an unknown entity: java.util.List
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:107)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1580)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1503)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1419)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1856)
at br.com.framework.hibernate.session.HibernateUtil.buildSessionFactory(HibernateUtil.java:38)
at br.com.framework.hibernate.session.HibernateUtil.<clinit>(HibernateUtil.java:30)
at br.com.project.filter.FilterOpenSessionInView.initFilterBean(FilterOpenSessionInView.java:43)
at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:179)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:285)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:266)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4699)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5339)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
   abr 14, 2018 7:18:26 PM org.apache.catalina.core.StandardContext filterStart
     GRAVE: Exception starting filter conexaoFilter
     java.lang.ExceptionInInitializerError: ERRO AO CRIAR A CONEXÃO SESSIONFACTORY!!
at br.com.framework.hibernate.session.HibernateUtil.buildSessionFactory(HibernateUtil.java:44)
at br.com.framework.hibernate.session.HibernateUtil.<clinit>(HibernateUtil.java:30)
at br.com.project.filter.FilterOpenSessionInView.initFilterBean(FilterOpenSessionInView.java:43)
at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:179)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:285)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:266)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4699)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5339)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Mantenho o @ManyToMany que a principo atualmente esta dando certo ou tentamos essa solução que falou?

O que estou fazendo hoje:::::

Deixei @ManyToMany do dois lados como no inicio.

Não estou gerando o combo. Quando estou criando o Setor ele fica na listagem Table e clico no setor assim jogando para uma tela de detalhes daquele setor em especifico e ali tem uma lista de procedimentos em dataTable que vou ADD clicando no procedimento que quero.

Não sei se mudar para como sugeriu abaixo, se ficaria melhor? Se ficar mudamos.

//um setor tem vários procedimentos
@OneToMany(cascade =  CascadeType.ALL, mappedBy = Setor.class)
private List<Procedimento> procedimentos = new ArrayList<Procedimento>();

//vários procedimentos de um setor
@ManyToOne
private List<Setor> setores = new ArrayList<Setor>();

@Rafael_Blum amigo desculpe-me, li o que escrevi e realmente eu estava errado, me confundi :crazy_face:, use o targetEntity = Setor.class e retire o mappedBy, você só precisa dele caso tenha classes de chave composta, caso contrário o jpa usa o atributo marcado com ‘@Id’.

Desculpa mesmo. :confused:

Esta gerando o erro:

 org.hibernate.AnnotationException: @OneToOne or @ManyToOne on 
br.com.project.model.classes.Procedimento.setores references an unknown entity: java.util.List
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:107)

O que percebo é que geralmente o relacionamento é tipo:

@OneToMany
List aqui = new…
e
@ManyToOne
Entidade enti = new… (AQUI NÃO É LISTA…)

Mas não sei né… não sou muito experiente ainda…

Posso ver o código diretamente em sua IDE, utilizando o TeamViewer?

Esse erro é típico de relacionamentos e da um pouco de trabalho para encontrar aonde está o problema, preciso ver o cenário todo.

Corrigimos e postamos a solução aqui.
tiagoadmstz@yahoo.com.br

Posso te passar os arquivos por email? Será que consegue ver o que é?
Tipo os pacotes (model, controllers, bensViews, etc)

E conseguindo, postamos a solução aqui.

não utilizo o eclipse, modelar o projeto inteiro novamente daria muito trabalho.

O erro que você mandou diz que você está fazendo referência a uma entidade desconhecida, a classe pode não estar anotada com ‘@Entity’, a classe pode não estar declarado no arquivo de configuração, o modelamento do relacionamento pode estar incorreto nas classes em questões(existem várias regras que devem ser seguidas).

Por isto é complicado de postar a solução aqui.

Os arquivo que tem relação são os abaixo:

Não precisa de alguma referencia para procedimento? Tipo JoinColumn(foreingKey=@ForeingKey(name="Setor_proced_fk))???

@Rafael_Blum

Vou analisar e posto a resposta logo mais.

@Rafael_Blum

@ManyToOne(fetch = FetchType.EAGER, targetEntity = Setor.class)
private List<Setor> setores; 

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Procedimento.class)
private List<Procedimento> procedimentos;

Amigo coloca assim que vai rodar.