-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Performance dilemma when inserting related entities
PostPosted: Sun Feb 27, 2011 2:55 pm 
Newbie

Joined: Sun Feb 27, 2011 9:45 am
Posts: 1
Hi!

Im am using Hibernate in "native mode" (not JPA), lets discuss the issue with two example entities (All Entities hav a String with a UUID as PK, the PK is generated in the constructor).

1. Developer
2. Project

Developer contains a unidirectional relation to Project:

@OneToOne(optional = true, cascade = { }, fetch = FetchType.LAZY)
private Project project;

The Session is in FlushMode.COMMIT.

When I create one Developer and one Project, and save() (or persist()) them, the resulting SQL statements depend on the order of events:

d = new Developer()
p = new Project()
d.setProject(p)
persist(d) // save(d) gives the same result
persist(p)
commit()

On flush/commit SQL is generated in the following order:
select project, insert Developer, insert Project

Question: Why does Hibernate fire the select? It is after the two persist calls, so Hibernate could know the referenced project exists in the session.

When I move the persist-calls before the d.setProject(p), I get:

insert Developer, insert Project, update Developer

Why the update? All the statements are fired on flush/commit...

I found two solutions which result in two inserts (without update/select)

1. Marke the relation as CascadeType.PERSIST
2. Reorder the persist calls: First Project, second Developer

The second solution is feasible in this little example, but difficult in production code with many entities.

The first solution works when the PK is a String. But in a legacy system I have a composite key: String mandant, String objectId. In the relations, the foreighn shares the column mandant with the primary key, so I had to map relations like this:

@Column(name = "project", length = 35)
private String projectObjectId;

@OneToOne(cascade = { }, fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="mandant", referencedColumnName="mandant", insertable=false, updatable=false),
@JoinColumn(name="project", referencedColumnName="ObjectId", insertable=false, updatable=false)
})
private Project project;

public void setProject(Project project) {
this.project = project;
projectObjectId = project != null ? project.getId().getObjectId() : null;
}

In this case, a CascadeType.PERSIST does not help, which is not surprising because the relation is read only.

Is there any configuration or other trick which avoids the unnecessary SQLs?
Do I have to order the persist-calls by myself? Another thing is Hibernates expects these calls when the entities are completely initialized, otherwise validation fails on non nullable properties.
From a programming view, the easiest thing would be to call persist direct after the constructor call, so the entity is part of the Session and I can never forget to persist it before commit.

Regards

Roger


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.