HIBERNATE - Relacionamento @ManyToOne grava registro de item existente novamente

Boa tarde a todos!

Sou novo em programação Java, e estou fazendo uma pequena aplicação web em JSP, utilizando Hibernate e banco de dados PostgreSQL.
Estou com um problema ao gravar os dados inseridos em um Bean de minha aplicação. Já pesquisei muito, e em vários outros fóruns, e não encontrei um caso semelhante ainda.
Dentre os dados das tabelas, vou citar somente os que considerei mais importantes. Preciso gravar os dados em uma tabela “Sessoes” e seus itens, no caso “Solicitacoes” (N:N). Para cada registro de “Solicitacoes”, deverá ser escolhido um de “Agencias” (1:N).
O meu problema é que, depois de inserir todos os dados, e escolher um de “Agencia” para “Soliciticacoes”, ao gravar o registro de “Sessao” (com “session.save(sessoes)”) está gravando novamente o registro de “Agencias”(que eu selecionei de uma lista dentre os já gravados).
Gostaria de saber o que fiz de errado.

Seguem abaixo os trechos de códigos das classes que considerei mais relevantes para este caso:

@Entity
@Table(name="sessoes")
@SuppressWarnings("serial")
public class Sessoes implements Serializable {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="id")
    @SequenceGenerator(name="id",sequenceName="sessoes_id_seq")
    @Column(name="id", nullable=false)
    private long id;
    
    
    @ManyToOne(fetch= FetchType.EAGER)
    @JoinColumn(name="id_usuario", insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.SAVE_UPDATE)
    private Usuarios usuarios;
    
    @ManyToMany(fetch= FetchType.LAZY)
    @JoinTable(name="itens_sessao", joinColumns={@JoinColumn(name="id_sessao")}
            , inverseJoinColumns={@JoinColumn(name="id_solicitacao")})
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.ALL)
    private List <Solicitacoes> solicitacoes;


}
@Entity
@Table(name = "solicitacoes")
@SuppressWarnings("serial")
public class Solicitacoes implements Serializable {
    
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="id")
    @SequenceGenerator(name="id",sequenceName="solicitacoes_id_seq")  
    @Column(name="id", nullable=false)
    private long id;

    @ManyToOne(fetch= FetchType.EAGER)
    @JoinColumn(name="id_pessoa", insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.ALL)
    
    private Pessoas pessoas;
    
    @ManyToOne(fetch= FetchType.EAGER)
    @JoinColumn(name="id_agencia", insertable=false, updatable=false)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.ALL)
    private Agencias agencias;
    
    @ManyToMany(fetch= FetchType.LAZY)
    @JoinTable(name="itens_sessao", joinColumns={@JoinColumn(name="id_solicitacao")},
            inverseJoinColumns={@JoinColumn(name="id_sessao")})
    private List<Sessoes> sessoes;

    public List<Sessoes> getSessoes() {
        return sessoes;
    }

}
@Embeddable
public class ItemSessaoPK implements Serializable {
    
    @ManyToOne(fetch= FetchType.EAGER)
    @JoinColumn(name="id_sessao")
    @Cascade(CascadeType.ALL)
    private Sessoes sessao;
    
    @ManyToOne(fetch= FetchType.EAGER)
    @JoinColumn(name="id_solicitacao")
    @Cascade(CascadeType.ALL)
    private Solicitacoes solicitacao;

}
@Entity
@Table(name="Itens_Sessao")
public class ItensSessao implements Serializable {
    
    @EmbeddedId
    private ItemSessaoPK chaveComposta;

    public ItemSessaoPK getChaveComposta() {
        return chaveComposta;
    }

    public void setChaveComposta(ItemSessaoPK chaveComposta) {
        this.chaveComposta = chaveComposta;
    }
    
}
@Entity
@Table(name = "agencias")
public class Agencias implements Serializable {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="id")
    @SequenceGenerator(name="id",sequenceName="agencias_id_seq")  
    @Column(name = "id", nullable = false)
    private long id;
    
    @OneToMany(mappedBy = "agencias", fetch= FetchType.LAZY)
    @Cascade(CascadeType.SAVE_UPDATE)
    private List<Solicitacoes> solicitacoes;

}

Desde já agradeço.

Abraços.

session.save

isto é para salvar mesmo, ta certo, se voce quer atualizar o mesmo registro, tem que usar o session.update, ou entao voce pode usar session.saveOrUpdate, que verifica se o objeto ja existe no banco e ao inves de salvar um novo registro, ele atualiza. Boa sorte.

Obrigado por responder rof20004!

Já tentei utilizar session.saveOrUpdate, mas ao selecionar uma agência (que já existe no bacno de dados) ele está tentando salvar novamente o registro, quando deveria apenas inserir o id no campo da chave estrangeira.
Já pensei em apenas colocar na classe um campo “id_agencia” ao invés da classe “agencia”, mas preciso do nome da agencia ao listar (isso sem falar que ficaria desorganizado).
Onde poderá estar o problema? Será que na forma em que insiro o objeto agencia em solicitacoes (ligada a sessao), ou em alguma configuracao hibernate das classes?

Abraço.

2 sugestoes:

  1. Quando voce for salvar o registro pela primeira vez no banco, faça o save normalmente.

  2. Quando voce for atualizar o mesmo, antes de manda-lo para o session.save, faça um get pelo ID do objeto, depois adicione as mudanças no objeto, e depois faça um session.save.

[quote=rof20004]2 sugestoes:

  1. Quando voce for salvar o registro pela primeira vez no banco, faça o save normalmente.

  2. Quando voce for atualizar o mesmo, antes de manda-lo para o session.save, faça um get pelo ID do objeto, depois adicione as mudanças no objeto, e depois faça um session.save.[/quote]

Olá rof20004!

Boa tarde!

Me desculpe demorar em responder suas sugestões.
Estava muito ocupado ultimamente.

Fiz como me pediu, realizei um "save para “sessao” (fazendo um commit inclusive), com o mesmo objeto, inseri as “solicitacoes”, relizando um comando “updatre”.
Mesmo assim continua tentando inserir “agencia” (vejo que realiza um comando insert).

Quando pego o objeto agencia utilizo o comando"

String sqlU = "from Agencias where (cnpj = :cnpj)"; session.createQuery(sqlU); age = (Agencias) session.createQuery(sqlU).setParameter("cnpj", cnpj).uniqueResult(); session.close();

Tem algum idéia do que posso estar fazendo errado?

Desde já agradeço por toda ajuda até agora.

Abraços.

Quando eu falo dar um get pelo ID, estou querendo dizer que antes de voce atualizar esse seu objeto, voce deve traze-lo do banco, e ai sim altera-lo, e depois persisti-lo. Tem a ver com a questao de Objeto Persistente e Transiente, acho que voce pegar no google umas explicacoes mais tecnicas sobre isso.

Bom, agora o codigo que voce mostrou, se refere a que ?

Vlw =D