Issue
I have an simple association between 2 entities:
public class Car {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
...
}
and
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private long userId;
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<Car> cars;
...
}
Then I get some user id from client. For example, userId == 5;
To save car with user I need to do next:
User user = ... .findOne(userId);
Car car = new Car();
car.setUser(user);
... .save(car);
My question is:
Can I persist car record without fetching user?
Similarly like I would do by using native SQL query: just insert userId like string(long) in Car table.
With 2nd lvl cache it will be faster but in my opinion I don't need to do extra movements.
The main reason that I don't want to use native Query is because I have much more difficult associations in my project and I need to .save(car) multiple times. Also i don't want to manually control order of query executions.
If I use session.createSQLQuery("insert into .....values()") will the Hibernate's batch insert work fine?
Correct me if I'm wrong.
Thanks in advance!
UPDATE:
Actually the mapping is similar to:
There is @ManyToMany association between User and Car. But cross table is also an entity which is named, for example, Passanger. So the mapping is next:
public class User{
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", targetEntity = Passenger.class)
private Set<Passenger> passengers;
}
Cross entity
@IdClass(value = PassengerPK.class)
public class Passenger {
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "car_id")
private Car car;
... other fields ...
}
Car entity:
public class Car {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "car", targetEntity = Passenger.class, cascade = CascadeType.ALL)
private Set<Passenger> passengers;
}
And the code:
List<User> users = ... .findInUserIds(userIds); // find user records where userId is IN userIds - collection with user Ids
Car car = new Car(); //initialization of car's fields is omitted
if (users != null) {
car.setPassengers(new HashSet<>(users.size()));
users.forEach((user) -> car.getPassengers().add(new Passenger(user, car)));
}
... .save(car);
Solution
"Can I persist car record without fetching user?"
Yes, that's one of the good sides of Hibernate proxies:
User user = entityManager.getReference(User.class, userId); // session.load() for native Session API
Car car = new Car();
car.setUser(user);
The key point here is to use EntityManager.getReference:
Get an instance, whose state may be lazily fetched.
Hibernate will just create the proxy based on the provided id, without fetching the entity from the database.
"If I use session.createSQLQuery("insert into .....values()") will the Hibernate's batch insert work fine?"
No, it will not. Queries are executed immediately.
Answered By - Dragan Bozanovic
Answer Checked By - Mildred Charles (JavaFixing Admin)