Chave composta JPA

2 respostas
diegohsi

Boa noite pessoal, desclpe mais nao consegui assimilar corretamente o mapeamento de chave composta, entendi que deve se crirar uma classId para tais, mais meu problema é o seguinte

tenho um DER e +- 10 entidades, pores tenho um m:n, logo fiz o mapeamneto incluindo minha classid, porem, minhas classes que são formam a chave composta tambem são relacionadas com outras classes ai esta o problema, enfim olha o meu mapeamento.

package br.com.locadora.dominio;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * The primary key class for the emprestimo database table.
 * 
 */
@Embeddable
public class EmprestimoPK implements Serializable {
	// default serial version id, required for serializable classes.
	private static final long serialVersionUID = 1L;

	@Column(name = "COD_DVD")
	private Integer codigoDvd;

	@Column(name = "COD_CLIENTE")
	private Integer codigoCliente;

	@Temporal(TemporalType.DATE)
	@Column(name = "DATA_EMPRESTIMO")
	private Date dataEmprestimo;

	public EmprestimoPK() {
	}

	public Integer getCodigoDvd() {
		return this.codigoDvd;
	}

	public void setCodigoDvd(Integer codDvd) {
		this.codigoDvd = codDvd;
	}

	public Integer getCodigoCliente() {
		return this.codigoCliente;
	}

	public void setCodigoCliente(Integer codCliente) {
		this.codigoCliente = codCliente;
	}

	public Date getDataEmprestimo() {
		return dataEmprestimo;
	}

	public void setDataEmprestimo(Date dataEmprestimo) {
		this.dataEmprestimo = dataEmprestimo;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		EmprestimoPK other = (EmprestimoPK) obj;
		if (codigoCliente == null) {
			if (other.codigoCliente != null)
				return false;
		} else if (!codigoCliente.equals(other.codigoCliente))
			return false;
		if (codigoDvd == null) {
			if (other.codigoDvd != null)
				return false;
		} else if (!codigoDvd.equals(other.codigoDvd))
			return false;
		if (dataEmprestimo == null) {
			if (other.dataEmprestimo != null)
				return false;
		} else if (!dataEmprestimo.equals(other.dataEmprestimo))
			return false;
		return true;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((codigoCliente == null) ? 0 : codigoCliente.hashCode());
		result = prime * result
				+ ((codigoDvd == null) ? 0 : codigoDvd.hashCode());
		result = prime * result
				+ ((dataEmprestimo == null) ? 0 : dataEmprestimo.hashCode());
		return result;
	}

	@Override
	public String toString() {
		return "EmprestimoPK [codigoDvd=" + codigoDvd + ", codigoCliente="
				+ codigoCliente + ", dataEmprestimo=" + dataEmprestimo + "]";
	}

}
package br.com.locadora.dominio;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;

/**
 * The persistent class for the emprestimo database table.
 * 
 */
@Entity
public class Emprestimo implements Serializable {
	private static final long serialVersionUID = 1L;

	@EmbeddedId
	private EmprestimoPK id;

	@Temporal(TemporalType.DATE)
	@Column(name = "DATA_DEVOLUCAO")
	private Date dataDevolucao;

	// @Temporal(TemporalType.DATE)
	// @Column(name = "DATA_EMPRESTIMO", insertable = false, updatable = false)
	// private Date dataEmprestimo;

	private Integer emprestado;

	@ManyToOne
	@JoinColumn(name = "COD_DVD", referencedColumnName = "CODIGO", insertable = false, updatable = false)
	private Dvd dvd;

	@ManyToOne
	@JoinColumn(name = "COD_CLIENTE", referencedColumnName = "CODIGO", insertable = false, updatable = false)
	private Cliente cliente;

	public Emprestimo() {
		this.id = new EmprestimoPK();
	}

	public EmprestimoPK getId() {
		return this.id;
	}

	public void setId(EmprestimoPK id) {
		this.id = id;
	}

	public Date getDataDevolucao() {
		return this.dataDevolucao;
	}

	public void setDataDevolucao(Date dataDevolucao) {
		this.dataDevolucao = dataDevolucao;
	}

	public Date getDataEmprestimo() {
		return this.id.getDataEmprestimo();
	}

	public void setDataEmprestimo(Date dataEmprestimo) {
		this.id.setDataEmprestimo(dataEmprestimo);
	}

	public Integer getEmprestado() {
		return this.emprestado;
	}

	public void setEmprestado(Integer emprestado) {
		this.emprestado = emprestado;
	}

	public Dvd getDvd() {
		return this.dvd;
	}

	public void setDvd(Dvd dvd) {
		this.dvd = dvd;
	}

	public Cliente getCliente() {
		return this.cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Emprestimo other = (Emprestimo) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Emprestimo [id=" + id + ", dataDevolucao=" + dataDevolucao
				+ ", emprestado=" + emprestado + ", dvd=" + dvd + ", cliente="
				+ cliente + "]";
	}

}
package br.com.locadora.dominio;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;

/**
 * The persistent class for the dvd database table.
 * 
 */
@Entity
public class Dvd implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Integer codigo;

	@Temporal(TemporalType.DATE)
	@Column(name = "DATA_GRAVACAO")
	private Date dataGravacao;

	@ManyToOne
	@JoinColumn(name = "COD_FILME")
	private Filme filme;

	@OneToMany(mappedBy = "dvd")
	private List<Emprestimo> emprestimos;

	public Dvd() {
	}

	public Integer getCodigo() {
		return this.codigo;
	}

	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}

	public Date getDataGravacao() {
		return this.dataGravacao;
	}

	public void setDataGravacao(Date dataGravacao) {
		this.dataGravacao = dataGravacao;
	}

	public Filme getFilme() {
		return this.filme;
	}

	public void setFilme(Filme filme) {
		this.filme = filme;
	}

	public List<Emprestimo> getEmprestimos() {
		return this.emprestimos;
	}

	public void setEmprestimos(List<Emprestimo> emprestimos) {
		this.emprestimos = emprestimos;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Dvd other = (Dvd) obj;
		if (codigo == null) {
			if (other.codigo != null)
				return false;
		} else if (!codigo.equals(other.codigo))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Dvd [codigo=" + codigo + ", dataGravacao=" + dataGravacao
				+ ", filme=" + filme + ", emprestimos=" + emprestimos + "]";
	}

}
package br.com.locadora.dominio;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;

/**
 * The persistent class for the cliente database table.
 * 
 */
@Entity
public class Cliente implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Integer codigo;

	@Temporal(TemporalType.DATE)
	@Column(name = "DATA_NASCIMENTO")
	private Date dataNascimento;

	private String email;

	private String nome;

	private String telefone;

	@OneToMany(mappedBy = "cliente")
	private List<Emprestimo> emprestimos;

	@OneToOne(mappedBy = "cliente")
	private Endereco endereco;

	public Cliente() {
	}

	public Integer getCodigo() {
		return this.codigo;
	}

	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}

	public Date getDataNascimento() {
		return this.dataNascimento;
	}

	public void setDataNascimento(Date dataNascimento) {
		this.dataNascimento = dataNascimento;
	}

	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getNome() {
		return this.nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getTelefone() {
		return this.telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}

	public List<Emprestimo> getEmprestimos() {
		return this.emprestimos;
	}

	public void setEmprestimos(List<Emprestimo> emprestimos) {
		this.emprestimos = emprestimos;
	}

	public Endereco getEndereco() {
		return this.endereco;
	}

	public void setEndereco(Endereco endereco) {
		this.endereco = endereco;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Cliente other = (Cliente) obj;
		if (codigo == null) {
			if (other.codigo != null)
				return false;
		} else if (!codigo.equals(other.codigo))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Cliente [codigo=" + codigo + ", dataNascimento="
				+ dataNascimento + ", email=" + email + ", nome=" + nome
				+ ", telefone=" + telefone + "]";
	}

	
}

chave composta cliente+dvd+dataemprestimo, logo cliente nao pode levar o mesmo dvd no mesmo dia.

o erro quando tento persistir apenas o emprestimo é o seguinte.
ERROR: Column 'COD_CLIENTE' cannot be null
javax.persistence.RollbackException: Error while committing the transaction
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92)
	at br.com.locadora.teste.TesteEmprestimo.service(TesteEmprestimo.java:96)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Column 'COD_CLIENTE' cannot be null
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
	... 18 more
Caused by: org.hibernate.exception.ConstraintViolationException: Column 'COD_CLIENTE' cannot be null
	at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
	at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
	at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
	at $Proxy18.executeUpdate(Unknown Source)
	at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2962)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3403)
	at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
	at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
	at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1214)
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403)
	at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
	... 18 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'COD_CLIENTE' cannot be null
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.Util.getInstance(Util.java:386)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
	at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2333)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2318)
	at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
	at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)

quando eu seto um cliente e um dvd (objetos) no emprestimo deveria popular a id cliente e id dvd do emprestimopk nao ?

2 Respostas

J

No caso vc precisa completar a chave composta( emprestimoPK), antes de tentar inserir. Como está com esse mapeamento de chave composta, e com os update e insert setado para false, o JPA precisa que voce informe isso previamente, antes de descer para a persistência. Isso funciona identicamente para recuperar valores, você informa os dados da PK( completa com os ID referentes) e requisita o objeto completo na persistência.

diegohsi
jaziel.rc:
No caso vc precisa completar a chave composta( emprestimoPK), antes de tentar inserir. Como está com esse mapeamento de chave composta, e com os update e insert setado para false, o JPA precisa que voce informe isso previamente, antes de descer para a persistência. Isso funciona identicamente para recuperar valores, você informa os dados da PK( completa com os ID referentes) e requisita o objeto completo na persistência.
hmm... fiz da seguinte forma para resolver esse problema, nao sei se é boa pratica, iniciei o obj id no construturo de emprestimo e meus get e set dos atributos chave fiz da seguinte forma
public Date getDataEmprestimo() {
		return this.id.getDataEmprestimo();
	}

	public void setDataEmprestimo(Date dataEmprestimo) {
		this.id.setDataEmprestimo(dataEmprestimo);
	}
public void setDvd(Dvd dvd) {
		this.dvd = dvd;
		this.id.setCodigoDvd(dvd.getCodigo());
	}
public Dvd getDvd() {
		return this.dvd;
	}
public void setCliente(Cliente cliente) {
		this.cliente = cliente;
		this.id.setCodigoCliente(cliente.getCodigo());
	}
public Cliente getCliente() {
		return this.cliente;
	}

Agora se eu entendi que vc disse, no meu caso eu teria que criar um id por exemplo, setar os valores e setar o id no obj emprestimo e persisitr ?

Criado 19 de janeiro de 2013
Ultima resposta 19 de jan. de 2013
Respostas 2
Participantes 2