Reputation: 740
I want to map my entities in the following manner:
I have a User and he buys a Car (a specific brand, model and variant).
To do this, I have created the following classes.
Car.java
@Entity
@Table(name="CARS")
public class Car {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="CAR_ID")
private int id;
@Column(name="CAR_MAKER")
private String maker;
@OneToMany(mappedBy="car")
private Collection<CarModel> models =new ArrayList<CarModel>();
......
Getters and Setters go here
......
}
CarModel.java
@Entity
@Table(name="CAR_MODELS")
public class CarModel {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="MODEL_ID")
private int modelId;
@Column(name="MODEL_NAME")
private String modelName;
@ManyToOne
@JoinColumn(name="CAR_ID")
private Car car;
@OneToMany(mappedBy="model")
private Collection<CarVariant> variants = new ArrayList<CarVariant>();
......
Getters and Setters go here
......
}
CarVariant.java
@Entity
@Table(name="CAR_VARIANT")
public class CarVariant {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column (name="VARIANT_ID")
private int variantId;
@Column(name="VARIANT_NAME")
private String variantName;
@Column(name="FUEL_TYPE")
private String fuelType;
@ManyToOne
@JoinColumn(name="MODEL_ID")
private CarModel model;
..........
Getters and setters go here
..........
}
And finally, User.java
@Entity
@Table(name="MASUSER")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_REC_ID")
private int recordId;
@Column(name="USER_ID")
private String id;
@Column(name="USER_NAME")
private String name;
@Column(name="USER_EMAIL_ID")
private String emailId;
@Column(name="USER_PHONE")
private String phone;
private Collection<Car> cars = new ArrayList<Car>();
}
Now, here's my question.
In real life, a user may own many cars, each one with a specific make, model and variant. I would like to implement such a feature with JPA/Hibernate.
I can define a @ManyToMany
relationship to User
and Car
. In that case, if I do user.getCars().getModels()
or user.getCars().getModels().get(0).getVariants()
I end up getting everything that's there in the DB.
How do I map User
and Car
in such a way that I get the following output?
--------------------------------------------------------
| USER_ID | CAR_ID | MODEL_ID | VARIANT_ID |
--------------------------------------------------------
| 1 | 1 | 2 | 3 |
--------------------------------------------------------
| 1 | 1 | 2 | 2 |
--------------------------------------------------------
| 3 | 2 | 1 | 1 |
--------------------------------------------------------
Also, if you feel I haven't designed my Entity classes right, please feel free to let me know how I can improve.
Thanks
Upvotes: 1
Views: 282
Reputation: 7469
It's not clear why you need such a table with all keys from nested relations.
My two cents:
@MappedSuperclass
public abstract class AbstractEntity
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column
private Long id;
......
Getters and Setters go here
......
}
@Entity
@Table(name = "MANUFACTURER")
public class Manufacturer extends AbstractEntity
{
@Column
private String name;
@OneToMany(mappedBy = "manufacturer")
private Set<CarModel> models = new LinkedHashSet<>();
......
Getters and Setters go here
......
}
@Entity
@Table(name = "CAR_MODEL")
public class CarModel extends AbstractEntity
{
@NotNull
@ManyToOne(optional = false)
@JoinColumn(name = "MANUFACTURER_ID")
private Manufacturer manufacturer;
@Column
private String name;
@OneToMany(mappedBy = "model")
private Set<CarVariant> variants = new LinkedHashSet<>();
......
Getters and Setters go here
......
}
@Entity
@Table(name = "CAR_VARIANT")
public class CarVariant extends AbstractEntity
{
@NotNull
@ManyToOne(optional = false)
@JoinColumn(name = "CAR_MODEL_ID")
private CarModel model;
@Column
private String name;
@Column(name="FUEL_TYPE")
private String fuelType;
@OneToMany(mappedBy="variant")
private Set<Car> cars = new LinkedHashSet<>();
......
Getters and Setters go here
......
}
@Entity
@Table(name = "CAR")
public class Car extends AbstractEntity
{
@NotNull
@ManyToOne(optional = false)
@JoinColumn(name = "CAR_VARIANT_ID")
private CarVariant variant;
@Column(name = "REGISTRATION_NUMBER")
private String registrationNumber;
@ManyToMany(mappedBy = "cars")
private Set<User> users = new LinkedHashSet<>();
......
Getters and Setters go here
......
}
@Entity
@Table(name = "USER")
public class User extends AbstractEntity
{
@Column
private String name;
@Column
private String email;
@Column
private String phone;
@ManyToMany
@JoinTable(name = "USER_CAR", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "CAR_ID"))
private Set<Car> cars = new LinkedHashSet<>();
......
Getters and Setters go here
......
}
Collection
s: use Set
s where possible (LinkedHashSet
), or List
s when you need an @OrderColumn
MODEL_NAME
, just use NAME
@MappedSuperclass
, especially if you have a surrogate id for all entitiesyou can now:
Car car = ...;
String manufacturerName = car.getVariant().getModel().getManufacturer().getName();
String jpql = "select c from Car c where c.variant.model.name = 'Golf' and c.variant.fuelType = 'Diesel'";
Upvotes: 0
Reputation:
If you fetch the main object like this
Criteria criteria=session.createCriteria(User.class);
List<Object> list=criteria.list();
User user=(User)list.get(0);
Car car=user.getCar();
CarModel carModel=car.getCarModel();
CarVarient carVarient=carModel.getCarVarient();
In this way you can get each object you are trying to fetch but keep in mind that you are using FethType.Lazy
And cascadeType.All in everyPojo
Upvotes: 1