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);
Persist should be called only on new entities, while merge is meant to reattach detached entities. If you're using the assigned generator, using merge instead of persist can cause a redundant SQL statement.
The entity class must be annotated with the Entity annotation or denoted in the XML descriptor as an entity. So, if you use annotations for mappings, @Entity is mandated by the specification and Hibernate has to adhere to it.
A persistent entity represents one row of the database and is always associated with some unique hibernate session. Changes to persistent objects are tracked by hibernate and are saved into the database when commit calls happen.
"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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With