[RESOLVIDO]Relacionamento n:n

Tenho a seguinte base:

[code]CREATE TABLE octopus (
idOctopus int(11) NOT NULL,
varOctopus varchar(45) DEFAULT NULL,
PRIMARY KEY (idOctopus)
);

CREATE TABLE valuesOctopus (
idValuesOctopus int(11) NOT NULL AUTO_INCREMENT,
idOctopus int(11) DEFAULT NULL,
alternative varchar(450) DEFAULT NULL,
valueAlternative int(11) DEFAULT NULL,
PRIMARY KEY (idValuesOctopus),
KEY varOctopus (idOctopus),
KEY octopus (idOctopus),
FOREIGN KEY (idOctopus) REFERENCES octopus (idOctopus) ON DELETE NO ACTION ON UPDATE NO ACTION
);

CREATE TABLE organization (
idOrganization int(11) NOT NULL AUTO_INCREMENT,
nameOrganization varchar(100) DEFAULT NULL,
descriptionOrganization varchar(100) DEFAULT NULL,
PRIMARY KEY (idOrganization)
) ;
CREATE TABLE project (
idProject int(11) NOT NULL AUTO_INCREMENT,
nameProject varchar(45) DEFAULT NULL,
descriptionProject varchar(10000) DEFAULT NULL,
idOrganization int(11) DEFAULT NULL,
PRIMARY KEY (idProject),
FOREIGN KEY (idOrganization) REFERENCES organization (idOrganization) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE projectvaluesoctopus (
idProject int(11) NOT NULL,
idValueOctopus int(11) NOT NULL,
primary key (idproject,idvalueoctopus),
FOREIGN KEY (idProject) REFERENCES project (idProject),
FOREIGN KEY (idValueOctopus) REFERENCES valuesoctopus (idValuesOctopus)
);
[/code]
olá amigos, a situaçao é a seguinte: tenho um relacionamento N:n entre project e valueOctopus, logo isso gera uma tabela relacionada (projectvaluesoctopus),estou usando mapeamento do eclipselink JPA. o mapeamento esta ok o problema esta na hora se inserir um novo projeto,pois, porque ele cria um novo registro em valuesoctopus(os valores dessa tabela sao pre-definidos e sao selecionados pelo usuario atraves de um selectItem) e em project (esta sim esta certa, pq estou criando um novo projeto). pesquisei sobre Casade.Type, strategy = GenerationType, so que ate agora nao obtive resultado. espero que alguem possa me dar uma luz. vlw!

  • Use a tag [code]
  • Qual a dificuldade encontrada para postar o mapeamento das classes em questão? Só ver as tabelas não nos diz muita coisa…

Poste suas classes de mapeamento e o seu DAO assim ficará mais fácil.

O strategy = GenerationType se refere como que será gerada a chave da tabela, e o Casade.Type se referem a forma de relacionamento de suas tabelas.

Sem o código de sua aplicação fica um pouco complicado dizer onde você está errando.

Olá joede.fadel,

sou amigo do rui e acompanho o desenvolvimento da aplicação dele, talvez possa contribuir com algumas informações a mais.

Na DAO(que é genérica) existem 3 métodos para a persistência das entidades:


// o objetivo deste a adicionar as classes a qual compôem a tabela relacionada permitindo efetivar(commit) em um outro momento
public void addToTranslation(Object o){
        if(!this.em.getTransaction().isActive()){
            this.em.getTransaction().begin();
        }
        this.em.persist(o);
}
// objetivo de comitar a transação ativa
public void commitCurrentTranslation(){
    this.em.getTransaction().commit();
}


// faz a mesma coisa que as anteriores, mas de uma só vez
    public void persist(Object object){
        EntityTransaction transation = this.em.getTransaction();
        transation.begin();
        this.em.persist(object);
        transation.commit();
    }

observe que consideramos que pelo fato do objeto precisar ser persistido na tabela relacionada, teríamos que adicionar os dois objetos previamente preparados na transação. Isto esta correto?

Quanto ao cascade, tentamos tirar de todos e continuou dando erro

Abraços

Classe Projeto

@Entity @Table(name = "project") @NamedQueries({ @NamedQuery(name = "Project.findAll", query = "SELECT p FROM Project p"), @NamedQuery(name = "Project.findByIdProject", query = "SELECT p FROM Project p WHERE p.idProject = :idProject"), @NamedQuery(name = "Project.findByNameProject", query = "SELECT p FROM Project p WHERE p.nameProject = :nameProject"), @NamedQuery(name = "Project.findByDescriptionProject", query = "SELECT p FROM Project p WHERE p.descriptionProject = :descriptionProject"), @NamedQuery(name = "Project.findByRpf", query = "SELECT p FROM Project p WHERE p.rpf = :rpf")}) public class Project implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "idProject") private Integer idProject; @Size(max = 45) @Column(name = "nameProject") private String nameProject; @Size(max = 10000) @Column(name = "descriptionProject") private String descriptionProject; @Column(name = "rpf") private Integer rpf; @JoinTable(name = "projectvaluesoctopus", joinColumns = { @JoinColumn(name = "idProject", referencedColumnName = "idProject")}, inverseJoinColumns = { @JoinColumn(name = "idValueOctopus", referencedColumnName = "idValuesOctopus")}) @ManyToMany(fetch = FetchType.LAZY) private List<ValuesOctopus> valuesOctopusList = new ArrayList<ValuesOctopus>(); @JoinColumn(name = "idOrganization", referencedColumnName = "idOrganization") @ManyToOne(fetch = FetchType.LAZY) private Organization idOrganization;

// gets e sets omitidos

classe ValuesOctopus

@Entity @Table(name = "valuesoctopus") @NamedQueries({ @NamedQuery(name = "ValuesOctopus.findAll", query = "SELECT v FROM ValuesOctopus v"), @NamedQuery(name = "ValuesOctopus.findByIdValuesOctopus", query = "SELECT v FROM ValuesOctopus v WHERE v.idValuesOctopus = :idValuesOctopus"), @NamedQuery(name = "ValuesOctopus.findByAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.alternative = :alternative"), @NamedQuery(name = "ValuesOctopus.findByValueAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.valueAlternative = :valueAlternative")}) public class ValuesOctopus implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "idValuesOctopus") private Integer idValuesOctopus; @Size(max = 450) @Column(name = "alternative") private String alternative; @Column(name = "valueAlternative") private Integer valueAlternative; @ManyToMany(mappedBy = "valuesOctopusList", fetch = FetchType.LAZY) private List<Project> projectList = new ArrayList<Project>(); @JoinColumn(name = "idOctopus", referencedColumnName = "idOctopus") @ManyToOne(fetch = FetchType.LAZY) private Octopus idOctopus;

//gets e sets omitidos

A questão é que quando adiciono um novo projeto e seto neste projeto um valueoctopus já existente, ele cria um novo valueoctopus com os mesmos valores porem com um id incrementado.

O seu DAO está correto, o problema está nas suas classes de mapeamento, os cascade não são errados olhe um exemplo:

...
public class pessoa {
  ...
@ManyToMany
 private List<Endereco> enderecoList;
...

 @XmlTransient
    public List<Endereco> getEnderecoList() {
        return enderecoList;
    }

    public void setEnderecoList(List<Endereco> enderecoList) {
        this.enderecoList= enderecoList;
    }

O objeto não será persistido por causa da annotation @XmlTransient, se ela for retirada seus dados serão persistidos.

[quote=rlorensi]Classe Projeto

@Entity @Table(name = "project") @NamedQueries({ @NamedQuery(name = "Project.findAll", query = "SELECT p FROM Project p"), @NamedQuery(name = "Project.findByIdProject", query = "SELECT p FROM Project p WHERE p.idProject = :idProject"), @NamedQuery(name = "Project.findByNameProject", query = "SELECT p FROM Project p WHERE p.nameProject = :nameProject"), @NamedQuery(name = "Project.findByDescriptionProject", query = "SELECT p FROM Project p WHERE p.descriptionProject = :descriptionProject"), @NamedQuery(name = "Project.findByRpf", query = "SELECT p FROM Project p WHERE p.rpf = :rpf")}) public class Project implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "idProject") private Integer idProject; @Size(max = 45) @Column(name = "nameProject") private String nameProject; @Size(max = 10000) @Column(name = "descriptionProject") private String descriptionProject; @Column(name = "rpf") private Integer rpf; @JoinTable(name = "projectvaluesoctopus", joinColumns = { @JoinColumn(name = "idProject", referencedColumnName = "idProject")}, inverseJoinColumns = { @JoinColumn(name = "idValueOctopus", referencedColumnName = "idValuesOctopus")}) @ManyToMany(fetch = FetchType.LAZY) private List<ValuesOctopus> valuesOctopusList = new ArrayList<ValuesOctopus>(); @JoinColumn(name = "idOrganization", referencedColumnName = "idOrganization") @ManyToOne(fetch = FetchType.LAZY) private Organization idOrganization;

// gets e sets omitidos

classe ValuesOctopus

@Entity @Table(name = "valuesoctopus") @NamedQueries({ @NamedQuery(name = "ValuesOctopus.findAll", query = "SELECT v FROM ValuesOctopus v"), @NamedQuery(name = "ValuesOctopus.findByIdValuesOctopus", query = "SELECT v FROM ValuesOctopus v WHERE v.idValuesOctopus = :idValuesOctopus"), @NamedQuery(name = "ValuesOctopus.findByAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.alternative = :alternative"), @NamedQuery(name = "ValuesOctopus.findByValueAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.valueAlternative = :valueAlternative")}) public class ValuesOctopus implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "idValuesOctopus") private Integer idValuesOctopus; @Size(max = 450) @Column(name = "alternative") private String alternative; @Column(name = "valueAlternative") private Integer valueAlternative; @ManyToMany(mappedBy = "valuesOctopusList", fetch = FetchType.LAZY) private List<Project> projectList = new ArrayList<Project>(); @JoinColumn(name = "idOctopus", referencedColumnName = "idOctopus") @ManyToOne(fetch = FetchType.LAZY) private Octopus idOctopus;

//gets e sets omitidos

A questão é que quando adiciono um novo projeto e seto neste projeto um valueoctopus já existente, ele cria um novo valueoctopus com os mesmos valores porem com um id incrementado.

[/quote]

Você gerou suas classes pele wizard do netbeans, o problema é o @XmlTransient nos gets

então joede.fadel, gerei pelo wizard sim, novas classes de entidades do banco, mas a questão é que ele persist os valores sim, porem, o id do valuesOctopus já existe, somente o projeto que é novo. e não encontrei essa anotation no meu codigo.

Poste os seu gets e sets, e se e exibido algum log também poste. Pois pelo que você relata não tem erro.

Classe project

[code]
/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package br.com.model;

import br.com.dao.OrganizationDAO;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.Size;

/**
*

  • @author Rui
    */
    @Entity
    @Table(name = “project”)
    @NamedQueries({
    @NamedQuery(name = “Project.findAll”, query = “SELECT p FROM Project p”),
    @NamedQuery(name = “Project.findByIdProject”, query = “SELECT p FROM Project p WHERE p.idProject = :idProject”),
    @NamedQuery(name = “Project.findByNameProject”, query = “SELECT p FROM Project p WHERE p.nameProject = :nameProject”),
    @NamedQuery(name = “Project.findByDescriptionProject”, query = “SELECT p FROM Project p WHERE p.descriptionProject = :descriptionProject”),
    @NamedQuery(name = “Project.findByRpf”, query = “SELECT p FROM Project p WHERE p.rpf = :rpf”)})
    public class Project implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = “idProject”)
    private Integer idProject;
    @Size(max = 45)
    @Column(name = “nameProject”)
    private String nameProject;
    @Size(max = 10000)
    @Column(name = “descriptionProject”)
    private String descriptionProject;
    @Column(name = “rpf”)
    private Integer rpf;
    @JoinTable(name = “projectvaluesoctopus”, joinColumns = {
    @JoinColumn(name = “idProject”, referencedColumnName = “idProject”)}, inverseJoinColumns = {
    @JoinColumn(name = “idValueOctopus”, referencedColumnName = “idValuesOctopus”)})
    @ManyToMany(fetch = FetchType.LAZY)
    private List valuesOctopusList = new ArrayList();
    @JoinColumn(name = “idOrganization”, referencedColumnName = “idOrganization”)
    @ManyToOne(fetch = FetchType.LAZY)
    private Organization idOrganization;

    public Project() {
    }

    public Project(Integer idProject) {
    this.idProject = idProject;
    }

    public Integer getIdProject() {
    return idProject;
    }

    public void setIdProject(Integer idProject) {
    this.idProject = idProject;
    }

    public String getNameProject() {
    return nameProject;
    }

    public void setNameProject(String nameProject) {
    this.nameProject = nameProject;
    }

    public String getDescriptionProject() {
    return descriptionProject;
    }

    public void setDescriptionProject(String descriptionProject) {
    this.descriptionProject = descriptionProject;
    }

    public Integer getRpf() {
    return rpf;
    }

    public void setRpf(Integer rpf) {
    this.rpf = rpf;
    }

    public List getValuesOctopusList() {
    return valuesOctopusList;
    }

    public void setValuesOctopusList(List valuesOctopusList) {
    this.valuesOctopusList = valuesOctopusList;
    }

    public Organization getIdOrganization() {
    return idOrganization;
    }

    public void setIdOrganization(Organization idOrganization) {
    this.idOrganization = idOrganization;
    }

    @Override
    public int hashCode() {
    int hash = 0;
    hash += (idProject != null ? idProject.hashCode() : 0);
    return hash;
    }

    @Override
    public boolean equals(Object object) {
    // TODO: Warning - this method won’t work in the case the id fields are not set
    if (!(object instanceof Project)) {
    return false;
    }
    Project other = (Project) object;
    if ((this.idProject == null && other.idProject != null) || (this.idProject != null && !this.idProject.equals(other.idProject))) {
    return false;
    }
    return true;
    }

    @Override
    public String toString() {
    return “br.com.model.Project[ idProject=” + idProject + " ]";
    }

    public void setIdOrganization(int organizationId) {
    OrganizationDAO organizationDAO = new OrganizationDAO();
    Organization organization = (Organization) organizationDAO.findById(organizationId);
    this.idOrganization = organization;
    }
    }[/code]

classe ValuesOctopus

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.Size;

/**
 *
 * @author Rui
 */
@Entity
@Table(name = "valuesoctopus")
@NamedQueries({
    @NamedQuery(name = "ValuesOctopus.findAll", query = "SELECT v FROM ValuesOctopus v"),
    @NamedQuery(name = "ValuesOctopus.findByIdValuesOctopus", query = "SELECT v FROM ValuesOctopus v WHERE v.idValuesOctopus = :idValuesOctopus"),
    @NamedQuery(name = "ValuesOctopus.findByAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.alternative = :alternative"),
    @NamedQuery(name = "ValuesOctopus.findByValueAlternative", query = "SELECT v FROM ValuesOctopus v WHERE v.valueAlternative = :valueAlternative")})
public class ValuesOctopus implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "idValuesOctopus")
    private Integer idValuesOctopus;
    @Size(max = 450)
    @Column(name = "alternative")
    private String alternative;
    @Column(name = "valueAlternative")
    private Integer valueAlternative;
    @ManyToMany(mappedBy = "valuesOctopusList", fetch = FetchType.LAZY)
    private List<Project> projectList = new ArrayList<Project>();
    @JoinColumn(name = "idOctopus", referencedColumnName = "idOctopus")
    @ManyToOne(fetch = FetchType.LAZY)
    private Octopus idOctopus;

    public ValuesOctopus() {
    }

    public ValuesOctopus(Integer idValuesOctopus) {
        this.idValuesOctopus = idValuesOctopus;
    }

    public Integer getIdValuesOctopus() {
        return idValuesOctopus;
    }

    public void setIdValuesOctopus(Integer idValuesOctopus) {
        this.idValuesOctopus = idValuesOctopus;
    }

    public String getAlternative() {
        return alternative;
    }

    public void setAlternative(String alternative) {
        this.alternative = alternative;
    }

    public Integer getValueAlternative() {
        return valueAlternative;
    }

    public void setValueAlternative(Integer valueAlternative) {
        this.valueAlternative = valueAlternative;
    }

    public List<Project> getProjectList() {
        return projectList;
    }

    public void setProjectList(List<Project> projectList) {
        this.projectList = projectList;
    }

    public Octopus getIdOctopus() {
        return idOctopus;
    }

    public void setIdOctopus(Octopus idOctopus) {
        this.idOctopus = idOctopus;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (idValuesOctopus != null ? idValuesOctopus.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof ValuesOctopus)) {
            return false;
        }
        ValuesOctopus other = (ValuesOctopus) object;
        if ((this.idValuesOctopus == null && other.idValuesOctopus != null) || (this.idValuesOctopus != null && !this.idValuesOctopus.equals(other.idValuesOctopus))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "br.com.model.ValuesOctopus[ idValuesOctopus=" + idValuesOctopus + " ]";
    }
    
}

Ele esta inserindo nas tabelas 3 tabelas relacionadas, porem, o certo seria inserir apenas um novo project e pegar o valueOctopus selecionado e inserir na tabela relacionada.

Achei o problema, que dizer, o luis.kaufmann.silva, lembrou de uma coisa muita importante. O objeto value octopus ja existe, então não preciso fazer commit dele e sim update adicionando um project. obrigado pela ajuda joede.fadel, rlorensi, drsmachado. vlw galera!