Stefan Falk
Stefan Falk

Reputation: 25387

How to persist "parent" entity when saving a "child" entity?

How can I let Hibernate save the "parent" entity e.g. if I have CarDescription that comes from a client via CarDescriptionDTO.

If I now want to save that e.g.

Session session = HibernateSession.openSession();
session.beginTransaction();

CarDescription carDescription = ConvertDTO.convertCarDescription(carDescriptionDto);

session.save(carDescription);

How can I make sure that a new Car entry gets created if carDescription does not have a Car set at this point? Or is this something I would not want Hibernate to do for me?

Car.java

@Entity
@Table(name = "car")
public class Car extends AbstractTimestampEntity implements Serializable {
    private static final long serialVersionUID = -5041816842632017838L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    // ..
}

how can I make sure that this also creates a Car entry?

CarDescription.java

@Entity
@Table(name = "car_description")
public class CarDescription extends AbstractTimestampEntity implements Serializable {
    private static final long serialVersionUID = 2840651722666001938L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @NotNull
    @ManyToOne
    private Car car;

    // ..
}

Upvotes: 1

Views: 1070

Answers (2)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 153720

That's not good practice. You shouldn't cascade entity state transitions from Child to Parents.

A better approach is to always check for the existing entities prior to populating the incoming data.

The flow will go like this:

Car car = session.get(Car.class, carId);
if(car == null) {
    car = new Car();
    session.persist(car);
}
CarDescription carDescription = session.get(CarDescription.class, carDescriptionId);
if(carDescription == null) {
    carDescription = new CarDescription();
    carDescription.setCar(car);
    session.persist(carDescription);
}

CarDescription carDescription = ConvertDTO.convertCarDescription(carDescriptionDto, car, carDescription);

This way you make sure the car and carDescription are associated with the current Session prior to populating the incoming data. Just calling persist will not trigger a database row insert, as it needs a flush for that. If you don't issue any query prior to populating your data, the entities will just be scheduled for flushing and propagated to the DB when the transaction commits.

Upvotes: 2

Dragan Bozanovic
Dragan Bozanovic

Reputation: 23552

There are two ways to achieve this.

1) You can create the Car in the CarDescription's field initializer:

@NotNull
@ManyToOne(cascade = CascadeType.PERSIST)
private Car car = new Car();

You also define CascadeType.PERSIST so that the car is persisted together with its CarDescription. This way a CarDescription will always have an empty car by default.

2) You can explicitly create and save the car:

Session session = HibernateSession.openSession();
session.beginTransaction();

CarDescription carDescription = ConvertDTO.convertCarDescription(carDescriptionDto);

Car car = new Car();
carDescription.setCar(car);

session.save(car);
session.save(carDescription);

Upvotes: 1

Related Questions