@IdClass and @GeneratedValue not working in Hibernate


#1

I use jpa and hibernate, I try to save an Icomposite pk

public class EmbedddedSamplesKey implements Serializable {

    private Integer id;
    private int year;
    ...
}

@Entity
@IdClass(EmbedddedSamplesKey.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Samplings {

    @Id
    @GeneratedValue
    private Integer id;

    @Id
    private int year;

    @OneToMany(mappedBy = "sampling", cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List<Samples> samples = new ArrayList<>();

    public void addSample(Samples sample) {
      samples.add(sample);
      sample.setSampling(this);
    }

    public void removeSample(Samples sample) {
      samples.remove(sample);
      sample.setSampling(null);
    }

    ...
}

@Entity
public class Samples extends BaseEntity {
    @Id
    @SequenceGenerator(name = "samples_id_seq", sequenceName = "samples_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "samples_id_seq")
    private Integer id;

    private String letter;

    @ManyToOne
    private Samplings sampling;
    ...
}

When I save I do

Samplings sampling =  new TraditionalSamplings();
samplings.setYear(LocalDate.now().getYear());

Samples sample = new Samples()
sample.setSampleLetter("A");

samplings.addSample(sample);

samplingRepository.save(samplings);

Samplings and samples are saved
but in samples table, sample_id_sampling_year there are not value

I was thinking theses values should be put automatically by hibernate?


#2

@IdClass and @GeneratedValue works properly in Hibernate. We have a test in the documentation folder that proves it.

The problem in your code comes from this mapping:

@ManyToOne
private Samplings sampling;

The Samples entity will expect a samplings_id FK to reference the Samplings table PK. But the Samplings table has a composite identifier.

Therefore, you need to use @JoinColumns:

@ManyToOne
@JoinColumns({
	@JoinColumn(
		name = "samplings_id",
		referencedColumnName = "id"),
	@JoinColumn(
		name = "samplings_year",
		referencedColumnName = "year")
})
private Samplings sampling;

For more details about mapping composite identifiers, check out the User Guide.


#3

just modified

@ManyToOne
    @JoinColumns({
        @JoinColumn(name = "sampling_id", referencedColumnName = "id"),
        @JoinColumn(name = "sampling_year", referencedColumnName = "year")})
    private Samplings sampling;

because field are sampling_id an sampling_year… so no “s”…

but still no value


#4

Show us the SQL log that gets executed along with the bind parameter values logged as well.


#5
Hibernate: 
    select
        nextval ('permacon.hibernate_sequence')
Hibernate: 
    select
        nextval ('permacon.samples_id_seq')
Hibernate: 
    select
        nextval ('permacon.samples_id_seq')
Hibernate: 
    select
        nextval ('permacon.samples_id_seq')
Hibernate: 
    select
        nextval ('permacon.samples_id_seq')
Hibernate: 
    select
        nextval ('permacon.samples_id_seq')
Hibernate: 
    insert 
    into
        permacon.samplings
        (available_for_test, build_date, reception_date, dtype, id, year) 
    values
        (?, ?, ?, 'TraditionalSamplings', ?, ?)
Hibernate: 
    insert 
    into
        permacon.samples
        (created_at, updated_at, sample_letter, sampling_id, sampling_year, id) 
    values
        (?, ?, ?, ?, ?, ?)
dtype	                id	year	available_for_test	build_date	reception_date	
TraditionalSamplings	59	2018	true	            2018-05-27	2018-05-27		
id	created_at	           updated_at	sample_letter	sampling_id	sampling_year
55	2018-05-27 09:16:02			

#6

Try changing the cascade to CascadeType.ALL:

@OneToMany(mappedBy = "sampling", cascade = CascadeType.ALL, orphanRemoval = true)

It might be that Spring Data called merge instead of persist because the composite identifier is an actual Object and not a null reference.


#7

you got it, thank

you know if that could possible to use in sample

idClass + sample_letter like a primary key?


#8

I’m glad it worked.

I don’t understand your last question. Is it that you want the composite identifer to include one more column?


#9

In sampling I use a composite key for the primary key

What I would like to do is to you use this composite key + another value for sample.

So many need to use a nested composite key?


#10

I have no idea what you are talking about.


#11

Actually I have
public class EmbedddedSamplesKey implements Serializable {

private Integer id;
private int year;
...

}

Who are used in Samplings

In sample for its pk I would like to use pk of Sampling + letter (from sample)


#12

Use @Id along with @ManyToOne. You should already know that from the User Guide chapter I mentioned earlier.