Bem vamos a explicação
Tenho uma tabela A com uma chave composta
tenho uma Tabela B que a chave primaria aponta para tabela A e tem mais um item na chave
Por exemplo
Table Nota Fiscal
-PK/FK EMPRESA
-PK/FK NUMERO NOTA
Table Nota Fiscal Item
-PK/FK EMPRESA
-PK/FK NUMERO NOTA
-PK Nr Item
public class NotaFiscalItem {
@EmbeddedId
private NotaFiscalItemPK pk;
//Esta parte em vez de estar na classe NotaFiscalItem ficou na PK
@ManyToOne
@JoinColumns({
@JoinColumn(name = "empresa", referencedColumnName="empresa", insertable = false, updatable = false),
@JoinColumn(name = "numero_nota", referencedColumnName="numero_nota", insertable = false, updatable = false)
})
private NotaFiscal notaFiscal;
}
Ficando assim
[code] @Embeddable
public class NotaFiscalPK implements Serializable {
Eu consegui fazer funcionar… mas tenho uma tabela que a PK/FK dela tem o mesmo nome que uma PK/FK da outra tabela que é FK da primeira rsrsr… vou exemplificar
Ex:
Table Empresa
PK cod_empresa
Table Operacoes
PK cod_operacao
PK/FK cod_empresa
Table Venda
PK controle
PK/FK cod_empresa
FK cod_operacao (minha duvida é aqui, acredito q ele tenta mapear um cod_empresa aqui tambem, ja que a tabela operaçoes tambem tem um cod_empresa)
Fiz assim:
Esse mapeamento Funciona!
@Embeddable
public class OperacoesPK implements Serializable {
@Column(name="cod_operacao")
private int codOperacao;
@Column (name="cod_empresa")
private int codEmpresa;
@Entity
public class Operacoes {
@EmbeddedId
private OperacoesPK pk;
Aqui por usar a mesma FK como PK ta dando pau
@Embeddable
public class VendaPK implements Serializable{
private Long controle;
private String serie;
@Column(name="cod_empresa")
private int codEmpresa;
@Entity
@Table(name="vendas")
public class Venda {
@EmbeddedId
private VendaPK pk;
@OneToOne
@JoinColumns({
@JoinColumn(name="cod_operacao", insertable=false, updatable=false),
@JoinColumn(name="cod_empresa", insertable=false, updatable=false)//acho que teria que ser só o joincolumn de cima, mas se deixar só ele dá erro porque a PK de operaçoes sao duas colunas
})
private Operacoes operacao;
Esqueci de falar do erro. Quando faço “select o from Operacoes” ele me retorna o resultado correto, com 30 registros. Porem quando eu faço “select v from Venda” ele faz duas selects, uma buscando as vendas e outra buscando as operaçoes.
nessa hora ele retorna o erro javax.persistence.EntityNotFoundException: Unable to find br.com.virage.mobile.modelo.Operacoes with id br.com.virage.mobile.modelo.OperacoesPK@cd8 o que é estranho, porque todos os cod_operacoes na tabela vendas estao cadastrados na tabela operacoes, assim como seu respectivo cod_empresa
Você está certo, falta o Join Column e mais um detalhe
@Embeddable
public class VendaPK implements Serializable{
private Long controle;
private String serie;
//Precisa ser Join Column
@Column(name="cod_empresa")
//não é um int é um objeto da Classe Entidade Empresa
private int codEmpresa;
coloquei como falou… faço a busca em todas as empresas… funciona… faço a busca em todas as operacoes… funciona… quando faço a busca em todas as Vendas ainda da erro (o hibernate monta a select tambem nas tabelas que estao relacionadas)
como se nao tivesse achando uma empresa com um determinado id. Todos os cod_empresa que tenho na tabelas vendas estao presentes na tabela empresa
classe e PK Vendas agora.
public class Venda {
@EmbeddedId
private VendaPK pk;
@OneToOne
@JoinColumns({
@JoinColumn(name="cod_operacao", insertable=false, updatable=false),
@JoinColumn(name="cod_empresa", insertable=false, updatable=false)
})
private Operacoes operacao;
Nao preciso instanciar um objeto Empresa dentro de venda nao né… ja que instanciei em minha PK
@Embeddable
public class VendaPK implements Serializable{
private Long controle;
private String serie;
@OneToOne
@JoinColumn(name="cod_empresa")
private Empresa codEmpresa;
Está com a anotaçao sim… tanto é q se eu deixar a classe sem vinculos com empresas e operaçoes ela funciona… há algo errado no relacionamento… o hibernate monta as selects na from vendas, from operacoes e from empresas (pra fazer o select em vendas ele levanta tambem a select dos relacionamentos) só q ele fala q algum ID nao foi encontrado… eu ja conferi todos…!! mas acho que sei o q ocorre…
Na minha tabela Venda eu nao sou obrigado a ter registro de todas as empresas … posso ter empresa que ainda nao vendeu… nao seria isso?? ele procura uma venda de uma empresa e nao encontra?
Meu mapeamento está igual o postado acima… nao vou postar de novo para aproveitar espaço
fiz o debug pelo log4j e percebi o seguinte…
minha tabela operaçoes tem a PK composta por cod_empresa e cod_operacao
na tabela vendas eu tenho minha PK composta por controle e cod_empresa
eu percebi q na primeira linha da minha tabela vendas… o cod_operacao=75 aí ele pega esse id e faz uma busca em empresa com o mesmo id… acredito que porque cod_empresa tambem faz parte da minha PK de cod_operacao
Acho que descobri o seu problema,
Voce mapeou errado a relação
Só existe uma venda por empresa?
se sim então OneToOne
se não é ManyToOne(varias vendas por empresa)
Realmente minha relaçao é manytoone… porem o problema ainda nao é esse…
Na tabela Vendas tenho uma FK cod_operacao, cod_operacao é parte da PK da tabela operacoes… a outra parte ta PK de operacoes é cod_empresa… tenho uma operacao com cod_operacao=75
quando faço From Operacoes me retorna tudo certinho… mas quando faço From Vendas … ele pega o cod_operaçao = 75 e faz uma busca na tabela empresas com esse codigo…
isso que nao entendo… vou postar como está agora.
OperacoesPK
@Embeddable
public class OperacoesPK implements Serializable {
@Column(name="cod_operacao")
private int codOperacao;
@ManyToOne
@JoinColumn (name="cod_empresa")
private Empresa codEmpesa;
Operacoes
[code]@Entity
public class Operacoes { @EmbeddedId
private OperacoesPK pk;
private String operacao;[/code]
Venda
@Entity
@Table(name="vendas")
public class Venda {
@EmbeddedId
private VendaPK pk;
@Column(name="total_servicos")
private BigDecimal totalServicos;
@Column(name="total_produtos")
private BigDecimal totalProdutos;
@ManyToOne
@JoinColumns({
@JoinColumn(name="cod_operacao", insertable=false, updatable=false),
@JoinColumn(name="cod_empresa", insertable=false, updatable=false)
})
private Operacoes operacao; // Comentando Operacoes assim como suas anotaçoes.. funciona normalmente
@Temporal(TemporalType.DATE)
private Calendar emissao = Calendar.getInstance();
ErroException in thread "main" javax.persistence.EntityNotFoundException: Unable to find br.com.virage.mobile.modelo.Empresa with id 75
Ele pega o codigo da operacao que está na tabela vendas (75 no caso) e faz uma busca na tabela empresa com esse valor… nao entendo o porque.
Isso mesmo!!! agora sim funcionou…Mas qual a necessidade do referencedcolumn se agente ja itentifica ela com o name?
Pra ficar 100% agora… o hibernate faz uma select pra tabela vendas… OK… mas está fazendo uma select pra cada cod_empresa que tenho… e um select pra cada cod_operacao (mais de 80)… dá pra mudar isso?
O referencedColumnName serve para o hibernate saber qual coluna exatamente da tabela de vendas esta ligada na sua relação, não basta ter o mesmo nome.
Essa parte dos selects eu não entendi sua duvida. Eu aqui uso o Oracle e ele faz apenas um select com Inner joins ligando as tabelas. e por causa do inner join ele faz um select em cada tabela para criar o objeto da outra tabela. é Meio estranho mas é assim mesmo.