Mapeamento JPA (Pedido-Itens)

5 respostas
D

Bom Dia Pessoal.

Já tentei de todos as formas mapear um relacionamento Pedido-Itens.
Não funciona na inclusão, porém, nas consultas e atualizações sem problema.

Não consegui identificar o que está errado. Segue o codigo abaixo:

Classe Pedidos:

public class Pedidos implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "cliente", nullable = false)
    private String cliente;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "idPedido")
    private Collection<Itens> itensCollection;

    // Construtor, getters e setters...
}

Classe Itens:

public class Itens implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "item", nullable = false)
    private String item;

    @JoinColumn(name = "id_pedido", referencedColumnName = "id")
    @ManyToOne
    private Pedidos idPedido;

    // Construtor, getters e setters...
}

Classe de teste:

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("TesteJPAPU");
        EntityManager em = factory.createEntityManager();
        
        ArrayList<Itens> itens = new ArrayList<Itens>();
        
        Itens item1 = new Itens();
        item1.setItem("Item1");
        itens.add(item1);
        
        Itens item2 = new Itens();
        item2.setItem("Item2");
        itens.add(item2);
        
        Pedidos pedido = new Pedidos();
        pedido.setCliente("Cliente1");
        pedido.setItensCollection(itens);
       
        //...
        em.getTransaction().begin();
        em.persist(pedido);
        em.getTransaction().commit();        
    }
    
    public static void main(String[] args) {
        // TODO code application logic here
        new Main();
    }
}

Script do Banco de dados MySql:

CREATE TABLE  `test`.`pedidos` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `cliente` varchar(45) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE  `test`.`itens` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `id_pedido` int(10) unsigned NOT NULL,
  `item` varchar(45) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `FK_itens_1` (`id_pedido`),
  CONSTRAINT `FK_itens_1` FOREIGN KEY (`id_pedido`) REFERENCES `pedidos` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Parte da exception lançada:

Exception in thread "main" javax.persistence.RollbackException: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build 060830)): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id_pedido' cannot be nullError Code: 1048
Call:INSERT INTO itens (item, id_pedido) VALUES (?, ?)
        bind => [Item1, null]
Query:InsertObjectQuery(testejpa.pojos.Itens[id=null])

Se alguem puder me ajudar? Agradeço…

5 Respostas

D

demys!

Talvez esteja acontecendo isto por voce estar inserindo os dois ao mesmo tempo e como nao foi dado o commit do pedido, qnd ele tentar buscar o idPedido, ele ainda não existe.

tente o seguinte:

inicie a transação.

insira o pedido sem itens;

e entao commit;
depois abra a transação novamente

insira os itens no objeto pedido e use o método merge como um update, para inserir os itens;

terminado commit novamente;

tente isso!!

Ab’s[]

V

bom, fiz uma breve analise, o problema é que você não está setando os valores que não pode ser nulo, como o id, o id_pedido.

D

Mas se eu fizer duas transações, perderá o sentido essencial da transação propriamente dita. Pode ocorrer pedidos órfãos, sem itens.

D

Correto, entendo o que você quer dizer estou passando pelo mesmo tropeço em minha empresa, engraçado…
usando ejb3 com pedidos e itens;

vamos entrar em um consenso, pense da seguinte forma, talvez não seja a correta mas vamos lá;

  • se um pedido não poder ser vazio, isto é uma regra de negócio entao tem que ser tradada antes de chegar na persistencia ok ?

você está tentanto atribuir a sua persistência algo seria de negócio, na minha situação eu posso ter um pedido sem itens,
mas não posso fatura-lo, chamamos o pedido de em composição;

verifique se vc está atribuindo as responsabilidades as classes certas;

Ab’s[]

D

Consegui resolver.

O que faltava era adicionar o pedido em cada item também.

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("TesteJPAPU");
        EntityManager em = factory.createEntityManager();
        
        Pedidos pedido = new Pedidos();
        pedido.setCliente("Cliente1");

        ArrayList<Itens> itens = new ArrayList<Itens>();
        
        Itens item1 = new Itens();
        item1.setPedido(pedido);
        item1.setItem("Item1");
        itens.add(item1);
        
        Itens item2 = new Itens();
        item2.setPedido(pedido); 
        item2.setItem("Item2");
        itens.add(item2);
        
        pedido.setItensCollection(itens);
       
        //...
        em.getTransaction().begin();
        em.persist(pedido);
        em.getTransaction().commit();        
    }
    
    public static void main(String[] args) {
        // TODO code application logic here
        new Main();
    }
}
Criado 30 de junho de 2008
Ultima resposta 9 de jul. de 2008
Respostas 5
Participantes 3