0

My Desired Behavior:

Make 
ID   |   City   |   Vers
1        Jose        S_5

MakeConfiguration
MakeID | Something | Vers
1         nada       S_5

When I get this entity (using spring data jpa with some custom @Query) then everything works fine.

When I try to post (the exact same entity), I want the following:

Make 
ID   |   City   |   Vers
1        Jose        S_5
1        Jose        S_6

MakeConfiguration
MakeID | Something | Vers
1         nada       S_5
1         nada       S_6

But what I get instead is this:

Make 
ID   |   City   |   Vers
1        Jose        S_5
1        Jose        S_6

MakeConfiguration
MakeID | Something | Vers
1         nada       S_6

(Notice the lack of new record created in MakeConfiguration) The SQL that is being shown is inserting a new record into Make, and updating the record in MakeConfiguration with the new Version. If I alter any of the other @Id annotated values (something, in this case) then it correctly inserts a new record. It seems that hibernate is not respecting the @Id annotation on the version.

I have the following (JPA/Hibernate entities)

@Entity
@IdClass(MakeId.class)
public class Make {
    @Id
    @Column(name="MAKE_ID")
    private String makeUuid;

    @Id
    private String city

    @Id @Column(name = "MAKE_ID_VERSION")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "version_seq")
    @GenericGenerator(
            name = "version_seq", strategy = "com.me.VersionIdGenerator"
    )
    private String makeIdVersion;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumns( {
            @JoinColumn(name = "clientProgramUuid", referencedColumnName = "MAKE_ID"),
            @JoinColumn(name = "clientUuidVersion", referencedColumnName = "MAKE_ID_VERSION")
    })
    private List<MakeConfiguration> makeConfigurations;
}

@Entity
@IdClass(MakeConfigurationId.class)
public class MakeConfiguration {
    @Id
    private String makeConfigurationUuid

    @Id
    private String something

    @Id
    private String makeIdVersion;
}

IdClass, getters, setters omitted for readability. VersionIdGenerator generates the next version in sequence (let us say S_1, S_2...S_N).

I also am always calling entitymanager.persist on Make entity.

I have tried several things to get this to work (bidirectional, etc.) and with no luck. I think that I need to force the version to be retrieved from what is generated by the Make.

Dave L
  • 29
  • 1
  • 2
  • Looks like a problem with your transactions... do you fetch the `MakeConfiguration` of version `5_5` and modify it? If so: does this all happen in one transaction? If yes: the entity is still attached and thus gets updated. This might be preventable if yout annotate the method fetching the `MakeConfiguration` with `@Transactional(propagation = Propagation.REQUIRES_NEW)` – Turing85 Sep 06 '19 at 17:59
  • No, My only interaction is through rest API (get + post), so nothing should be attached still – Dave L Sep 06 '19 at 18:29
  • There seems to be a misunderstanding here... in your app, you need to have some code (probably a `Repository`) interacting with the database. There must be some transactions be involved. No transactions = no database interaction. – Turing85 Sep 06 '19 at 18:31

1 Answers1

0

First of all, never use Eager) Use FetchType.LAZY.
Check this question

Second, never use @id a lot. Use it only once per Entity. @Id: This annotation specifies the primary key of the entity. Even if you placing in the column id of some object - just simply use @Column
Check this question

Btw, download ProjectLombok library (for Maven):

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

I fixed your program. It should look like this:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table
@Entity
public class Make {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "version_generator")
    @SequenceGenerator(name = "version_generator", sequenceName = "seq_version", allocationSize = 1)
    private Long id;

    @Column
    private String makeUuid;

    @Column
    private String city;

    @OneToMany(
            cascade = {
                    CascadeType.MERGE,
                    CascadeType.PERSIST
            }, fetch = FetchType.LAZY
    )
    private List<MakeConfiguration> makeConfigurations = new ArrayList<>();

    public void addMakeConfigurations(MakeConfiguration makeConfiguration) {
        makeConfigurations.add(makeConfiguration);
    }

    public void removeMakeConfigurations(MakeConfiguration makeConfiguration) {
        makeConfigurations.remove(makeConfiguration);
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table
@Entity
public class MakeConfiguration {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "makeConfig_generator")
    @SequenceGenerator(name = "makeConfig_generator", sequenceName = "seq_makeConfig", allocationSize = 1)
    private Long id;

    @Column
    private String makeConfigurationUuid;

    @Column
    private String something;

    @Column
    private String version;
}
Antonio112009
  • 415
  • 2
  • 7
  • 21