Relacionamento CascadeType

44 respostas Resolvido
java
R

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>();

44 Respostas

H

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

V

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.

R

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)?

V

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.

R

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:

R

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>();
V

@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.

R

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?

R

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>();
V

@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:

R

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)
R

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…

V

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.
[email removido]

R

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.

V

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

V

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.

R

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))???

V

@Rafael_Blum

Vou analisar e posto a resposta logo mais.

V
Solucao aceita

@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.

V

Cara o hibernate está reclamando por que você está colocando as anotações diretamente nos atributos, como uma boa prática sempre colocamos as anotações nos getters para não ocorrer quebra de encapsulamento.

@Entity

@Table(name = setor)

@Access(AccessType.PROPERTY)

public class Setor{

private Long id;

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

public Long getId(){}

}

R

Na faculdade e nas vídeo aulas sempre ensinaram da forma que faço. Acho que não é isso, mesmo por que eu mudei agora como falou e gerou:

Could not determine type for: java.util.list, at table: setor, for column: [org.hibernate.mapping.column(procedimento)]
V

@Rafael_Blum

Este é outro erro, agora ele está dizendo que não consegue determinar o tipo para java.util.list na tabela setor para a coluna procedimento.

Agora para saber o por que preciso ver as classes modificadas.

V

Tente fazer o drop das tabelas e deixe o hibernate recria-las sozinho

R

Eu tinha dropado todas tabelas de setor, procedimento… e dai ele criou tudo certinho, OK.
Entrou no sistema… tela inicial OK
Clico no botão de entrar na tela de cadastro do procedimento e gera erro.

V

Tenta não criar as listas dentro do objeto, tira o new ArrayList.

R

Vou tentar… :slight_smile:
Amanhã ajusto e tento e lhe falo brow… to caindo de sono :+1::+1:

R

Utilizando o select * from procedimento no MySQL, procedimento fica com uma coluna_id, é normal?

R

E outra coisa,
Fiz desta mesma forma que me falou para um outro relacionamento em meu projeto que é PEDIDO tem muito PRODUTOS (só pedido enxerga os produto).
Confirma tmb, utilizar assim?

Já estou bem confuso nisso?

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = RequisicaoDeCompra.class)
private List<Produto> produtos = new ArrayList<Produto>();

:

@ManyToOne(fetch = FetchType.EAGER, targetEntity = Produto.class)
private List<RequisicaoDeCompra> pedidos = new ArrayList<RequisicaoDeCompra>();
V

@Rafael_Blum Desculpe a demora em responder, mas como não me marcou não apareceu a notificação para mim.
Explica um pouco melhor, não entendi o problema.

Muitas vezes em um relacionamento de tabelas principalmente no caso de pedidos e produtos é normal o pedido conhecer seus produtos mas os produtos não sabem de qual pedido são, caso queira que o produto guarde o número de id do pedido basta adicionar a anotação JoinColumn ao seu atributo.

R

Fiz assim e funcionou.
Agora queria saber, cada procedimento fica com uma coluna de setor_id? Ela é obrigatória, porque? É que tenho uma tela que crio o procedimento e nela não quero vincular ao setor, somente quando eu criar o setor e adicionando proced.

E percebi que as vezes temos problemas com a questão do fetch = FetchType.EAGER. Por que queremos listar e tal… vou ter problemas em criar o setor e adicionar o procedimentos?

V

@Rafael_Blum nesse tipo de relacionamento o banco cria uma terceira tabela, os procedimentos tem de ser vinculados ao setor pelo id, mas quando vc criar um setor você pode ou não informar um procedimento e o mesmo vale pro lado inverso. Tudo fica a critério da sua imaginação na hora de programar.

R

Na realidade, Villagram, estou utilizando esta mesma dica que me falou na relação de pedido e produto, esta correto da mesma forma né?

Na minha tela quando crio o produto, gera o erro:

org.hibernate.PropertyAccessException: could not get a field value by reflection getter of 
br.com.project.model.classes.RequisicaoDeCompra.id
V

Ele está reclamando que está anotando o campo ao em vez do getter, ou esquecendo de colocar o @Access

R

Erro:

org.hibernate.MappingException: Could not determine type for: java.util.List, at table: requisicaoDeCompra, for columns: [org.hibernate.mapping.Column(produtos)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:306)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:290)
at org.hibernate.mapping.Property.isValid(Property.java:217)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:464)
at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1362)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1865)
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 29, 2018 10:54:05 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)

  abr 29, 2018 10:54:05 PM org.apache.catalina.core.StandardContext startInternal
   GRAVE: One or more Filters failed to start. Full details will be found in the appropriate container 
    log file
      abr 29, 2018 10:54:05 PM org.apache.catalina.core.StandardContext startInternal
     GRAVE: Context [/ger-industrialatividadesdynamico] startup failed due to previous errors
    abr 29, 2018 10:54:05 PM org.apache.catalina.core.ApplicationContext log
    INFORMAÇÕES: Closing Spring root WebApplicationContext
    6439 [localhost-startStop-1] INFO                                                         
    org.springframework.web.context.support.XmlWebApplicationContext - Closing Root         
     WebApplicationContext: startup date [Sun Apr 29 22:53:58 BRT 2018]; root of context 
       hierarchy
     6439 [localhost-startStop-1] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@68f83aa8: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0,org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0,org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0,org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#1,contaRazaoController,documentoController,entidadeController,fornecedorController,procedimentoController,produtoController,requisicaoController,setorController,srvContaRazaoImpl,srvDocumentoImpl,srvEntida

R

Não tem uma forma mais fácil de fazer este relacionamento?

V

Cara o problema não é a anotação do id, agora o problema é esse new ArrayList() o hibernate não aceita isto.

R

Mas eu uso no projeto relacionamentos com List e utilizo new ArrayList e funciona normal.

O que me sugere?

Desculpa lhe atrapalhar ai brow.

V

Dentro da classe de objeto não inicialize a lista, faça isso onde você instancia ela ou no construtor dela.

R

Funcionou mesmo.

Você quer me dizer que agora eu inicializo a List na RequisicaoBean para ir adicionando os produtos?

E me diz, vou adicionando os produtos e automaticamente a coluna com id da requisicao em produto ficara com id da requisicao? Isso?

V

Isto mesmo, crie a lista no RequisicaoBean e adicione os produtos.

Salve o objeto inteiro que contém a lista…o hibernate faz o resto.

R

Sim, muito obrigado, Villagram!!! :slight_smile:

Gostaria de ver com você se pode me ajudar em outras questões do meu projeto. Não realizei ainda, mas nem sei por onde começar.

Tem como em outras postagens te chamar ou te marcar?

V

@Rafael_Blum Tem como marcar sim, mas se precisar pode me procurar pelo e-mail também…[email removido]

R

Ta ok!!! Obrigado!!! valew mesmo!! E desculpe lhe atrapalhar!! :slight_smile: :slight_smile:

Vou marcar a resposta lá!!!

R
Ola, Villagram

Poderia me ajudar no topico?

<aside class="quote" data-post="1" data-topic="368918">
  <div class="title">
    <div class="quote-controls"></div>
    <img alt="" width="20" height="20" src="/user_avatar/www.guj.com.br/rafael_blum/40/95082_1.png" class="avatar">
    <a href="//www.guj.com.br/t/selectonemenu-converter-de-string-para-int/368918?source_topic_id=366414">SelectOneMenu converter de String para int</a> <a class="badge-wrapper  bullet" href="/c/programacao/java">Java</a>
  </div>
  <blockquote>
    Ola, pessoal 
Estou desenvolvendo uma cadastro que seja mais rapido e a ideia é que o usuário escolha o código de um produto  cadastrado e escolhendo o código os campos de material e nome  fiquem prenchidos, assim não teremos cadastros errados. 
Meu problema é que o material é do tipo int e o meu combo/converte busca por string. Poderiam me ajudar? 
Tela: 
 <a class="lightbox" href="/uploads/3X/f/f/ff71773f437b9797785149ca24d4dc5fb64ec5c1.JPG.webp" title="Capturar.JPG">[Capturar]</a>
::Entidade PRODUTO 
@Audited
@Entity
@Table(name = "produto")
public class Produto implements Serializable{

private static
  </blockquote>
</aside>
Criado 8 de abril de 2018
Ultima resposta 20 de mai. de 2018
Respostas 44
Participantes 3