0

I have a unidirectional, one-to-many, parent/child relation. In my test case, I have 1 parent with 2 children which are inserted via cascading insert.

Looking at the queries that are ran, I have 1 insert for the parent, 1 insert and two update queries for each of the children. The updates for the foreign key - they are setting the parent_id column in the child table, but I can see that the parent_id has already been set correctly by the insert.

Here is an example

@Entity
@Table(name = "PARENT")
public class Parent
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long parentId;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", nullable=false)
    private List<Child> children;
}

@Entity
@Table(name = "CHILD")
public class Child 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @Column(name = "PARENT_ID")
    private Long parentId;

    //some other field
}

//The test looks like this

Parent parent = new Parent();
Child child1 = new Child();
Child child2 = new Child();
//set all fields

parent.addChild(child1);
parent.addChild(child2);

em.merge(parent);

Is it possible to not have the update queries? Is it possible to insert all children in a single query?

ventsyv
  • 3,316
  • 3
  • 27
  • 49
  • 1
    How are you inserting them? Merge or persist? Post some code. – mikeb Nov 19 '15 at 19:38
  • Merge. The code is trivial, I simply call merge on the parent object. – ventsyv Nov 19 '15 at 19:39
  • "trivial" Well yes it is and yes it isn't - if you're using a canned process within the api to automate these chained statements but you are trying to mitigate what amounts to failsafe calls, then "trivial" isn't how i would describe it. The updates (from what I remember of my java days, about 3 years ago) are there for continuity purposes - i type slow - Anuj beat me to it- but basically, in a distributed system the parent object/table is available potentially before the child are and the updates are a necessity – Brandt Solovij Nov 19 '15 at 19:45

2 Answers2

1

You might try persist instead of merge

JPA EntityManager: Why use persist() over merge()?

Community
  • 1
  • 1
mikeb
  • 10,578
  • 7
  • 62
  • 120
-1

No. It is not possible. because after insert in parent table, a child table can be inserted.

Anuj Panwar
  • 113
  • 7
  • 1
    This doesn't make sense (not at the SQL level at least). If the parent is inserted _before_ the children, then surely the PK of the parent is known and there is no need to run one update for each child after they are inserted. –  Nov 19 '15 at 19:47
  • @a_horse_with_no_name - unless the parent is assigned a lock at update/creation time - you could see race condition occur (and likely will) on any system with moderate, concurrent use – Brandt Solovij Nov 19 '15 at 19:49
  • I agree. I have logging enabled and I do see not only that the parent row is being inserted, but also that the child row is inserted WITH the correct parent ID. The updates are totally unnecessary. – ventsyv Nov 19 '15 at 19:49
  • @BrandtSolovij: the parent is not visible outside the transaction so it's useless to "lock" it. And the child rows are also not visible outside the transaction, so there is no lock necessary either. So where should a race condition come from? –  Nov 19 '15 at 20:15