YASHI GUPTA
YASHI GUPTA

Reputation: 41

many to one association inserts instead of update

My Parent class

@Entity
public class Trailer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = “trailer_id", nullable = false)
    private Long trailerId;

    @OneToMany(mappedBy = “trailer”,cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private Set<Item> items;
}

Child class

@Entity
public class Item {

    @Id
    @Column(name = “upc”, nullable = false)
    private Long upc;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "trailer_id", referencedColumnName = "trailer_id")
    private Trailer trailer;
}

A Trailer can have multiple unique Items, but the same trailer may bring different set of unique items later.

Service Class

 public void addOrderToDB() {

        List<Trailer> trailer = new ArrayList<>();
        List<Item> items = new ArrayList<>();
        

        trailer = Trailer.builder().build();
        Item item1 = Item.builder().setTrailer(trailer).build();
        Item item2 = Item.builder().setTrailer(trailer).build();

        items.add(item1)
        items.add(item2)
       
        ItemRepository.saveAll(items);
}

Why am i trying to saving from many side: because the unique key is upc here.

At the time i am inserting the Item, it is inserting new entry for the Trailer corresponding to each Item entry of the same object.

Expected output:

Trailer table
trailer_id
1

Item table 
trailer_id  upc
  1         001
  1         002

Actual output:

Trailer table
trailer_id
1
2

Item table 
trailer_id  upc
  2         001
  2         002

Upvotes: 3

Views: 1385

Answers (2)

prenoramance
prenoramance

Reputation: 14

@Entity
public class Trailer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = “trailer_id", nullable = false)
    private Long trailerId;

    @OneToMany(mappedBy = “trailer”,cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private Set<Item> items = new HashSet<>();
}

Remove redendent:

@Entity
public class Item {

    @Id
    @Column(name = “upc”, nullable = false)
    private Long upc;
}

then,

public void addOrderToDB() {

        List<Trailer> trailer = new ArrayList<>();
        List<Item> items = new ArrayList<>();
        

        trailer = Trailer.builder().build();
        Item item1 = Item.builder().build();
        Item item2 = Item.builder().build();

        trailer.add(item1);
        trailer.add(item2);

        items.add(item1);
        items.add(item2);
       
        ItemRepository.saveAll(items);
}

Upvotes: 0

Felix Seifert
Felix Seifert

Reputation: 602

Your issue is that you do not synchronise the relationships properly: You make each Item aware of its Trailer but not the other way around. A nice way to do this is to have an add and a remove method in your parent object.

@Entity
public class Trailer {
    ...

    void addItem(Item item) {
        items.add(item);
        item.setTrailer(this);
    }

    void removeItem(Item item) {
        items.remove(item);
        item.setTrailer(null);
    }

    ...
}

You then add each new Item to the respective Trailer with the addItem method. It might then not be relevant from which side you save. Keys have to be unique anyway, just have a look how you generate the key for Item.

trailer.addItem(item1);
trailer.addItem(item2);
repository.save(trailer);

Upvotes: 1

Related Questions