Problemas ao updatar Collections - Hibernate

6 respostas
Pablo_Eteg

Pessoal tenho o seguinte problema quando tento persistir no banco de dados uma Collection, no caso um List.

O Hibernate tenta executar a seguinte query:
update sf2_dispensaprescricaoitem set dispensaprescricao_id=null where dispensaprescricao_id=? and id=?

como o campo dispensaprescricao_id é not null recebo o erro de violação de contraints.

Tenho um objeto original que possui um list como propriedade eu altero os valores do seu List e tento aplicar
o saveOrUpdate ao objeto.

Antes da gravar o objeto no banco seto em todos os objetos do list a propriedade que corresponde ao campo dispensaprescricao_id

for (DispensaPrescricaoItem dispensaPrescricaoItem2 : dispensaPrescricao.getItens()) {			
	dispensaPrescricaoItem2.setDispensaPrescricao(dispensaPrescricao);
}
        saveOrUpdate(dispensaPrescricao);

e mesmo assim recebo o erro de excessão
java.sql.BatchUpdateException: Column ‘dispensaprescricao_id’ cannot be null

Estou fazendo algo errado ao gravar no banco?

6 Respostas

andrefariagomes

Oi Pablo,

Me parace que você está esquecendo de associar o “detail” ao “master”, algo como:
dispensaPrescricaoItem.setDispensaPrescricao(dispensaPrescricao);

Certo?

Pablo_Eteg

andrefariagomes:
Oi Pablo,

Me parace que você está esquecendo de associar o “detail” ao “master”, algo como:
dispensaPrescricaoItem.setDispensaPrescricao(dispensaPrescricao);

Certo?

Na verdade é isto o que estou fazendo no for antes do saveOrUpdate mas mesmo assim
o erro persiste.

andrefariagomes

Então talvez você não tenha associado uma sequence ao DispensaPrescricao…
e banco de dados está tentando gravar null na PrimaryKey o que gera a violção.

É um objeto novo, ou você alterando?
Está salvado o pai antes do filho? quero dizer o DispensaPrescricao antes do DispensaPrescricaoItem?
Se não pode tentar usar @Cascade

Algo como:

@Entity

@SequenceGenerator(name = SEQUENCIA_PESSOA, sequenceName = SEQUENCIA_PESSOA)

@Table(name = PESSOA)

public class Pessoa implements Serializable {

@Id

@GeneratedValue(generator = SEQUENCIA_PESSOA)

@Column(name = PESSOA_KEY)

public Integer getPessoaKey() {

return pessoaKey;

}

}
Pablo_Eteg

andrefariagomes:
Então talvez você não tenha associado uma sequence ao DispensaPrescricao…
e banco de dados está tentando gravar null na PrimaryKey o que gera a violção.

É um objeto novo, ou você alterando?
Está salvado o pai antes do filho? quero dizer o DispensaPrescricao antes do DispensaPrescricaoItem?
Se não pode tentar usar @Cascade

Algo como:

@Entity

@SequenceGenerator(name = SEQUENCIA_PESSOA, sequenceName = SEQUENCIA_PESSOA)

@Table(name = PESSOA)

public class Pessoa implements Serializable {

@Id

@GeneratedValue(generator = SEQUENCIA_PESSOA)

@Column(name = PESSOA_KEY)

public Integer getPessoaKey() {

return pessoaKey;

}

}

Você pode me explicar melhor esse Sequence, para o que necessariamente ele serve?

O meu mapeamento na classe pai é o seguinte:

@SuppressWarnings("serial")
@Entity
@Table(name = "sf2_dispensaprescricao")
public class DispensaPrescricao implements Serializable{
        @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return id;
	}

        @OneToMany
	@Cascade( { CascadeType.ALL, CascadeType.DELETE_ORPHAN })
	@JoinColumn(name = "dispensaprescricao_id")
	public List<DispensaPrescricaoItem> getItensPrescricao() {
		return itensPrescricao;
	}

       //...outras propriedades
}

e o da classe filha eh este:

@SuppressWarnings("serial")
@Entity
@Table(name = "sf2_dispensaprescricaoitem")
public class DispensaPrescricaoItem implements Serializable {
        @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return id;
	}
      //..seu set
@ManyToOne
	@JoinColumn(name = "dispensaprescricao_id" , nullable = false)
	public DispensaPrescricao getDispensaPrescricao() {
		return dispensaPrescricao;
	}
        //..seu set
       //..outras propriedades
}
andrefariagomes

Sequences são usadas por alguns banco de dados como o oracle, por exemplo, para armazenar números, geralmente são utilizadas para gerar valores de primary keys, no seu caso, pelo que vi no seu mapeamento está gerando uma abordagem IDENTITY, então não precisa declarar mesmo a sequence.

No exemplo que postei a cima, cada vez que incluo uma registro na tabela PESSOA, a sequence é invocada, e o valor de retorno é associado à chave primaria do novo registro e o valor da sequence é incrementado para que na próxima vez que for envocada o valor seja diferente.

Derrepende vale a pena verificar se o banco de dados que você está usando suporta esse tipo de Generator.
Você tem certeza que valor de dispensaPrescricao.getId() que você associou ao dispensaPrescricaoItem não está nulo?

Pablo_Eteg

Consegui resolver.

O problema era que na minha página eu copiava o arrayList
alterava seu dados e depois dava um addAll na lista que eu ia
gravar no banco.

Parei de fazer o addAll e atribuí valor por valor em um loop
no objeto que ia ser persistido no banco aih funcionou.

Acho que ao dar addAll o hibernate não conseguia associar a minha lista com o banco de Dados.

Vlw pela ajuda Andre

Criado 24 de maio de 2008
Ultima resposta 25 de mai. de 2008
Respostas 6
Participantes 2