Chave composta JPA

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.

[code]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 + "]";
}

}[/code]

[code]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 + "]";
}

}[/code][code]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 + "]";
}

}[/code][code]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 + "]";
}

}[/code]

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 ?

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

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

public void setDataEmprestimo(Date dataEmprestimo) {
	this.id.setDataEmprestimo(dataEmprestimo);
}[/code][code]public void setDvd(Dvd dvd) {
	this.dvd = dvd;
	this.id.setCodigoDvd(dvd.getCodigo());
}[/code]

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 ?