Reputation: 141
I am currently trying to learn hibernate and have encountered a problem which looks reasonable from both OOP and DB point of view, and yet I am unable to find solution.
My java part looks more or less like this:
@Entity
@Table (name = "Vehicles")
class Vehicle {
@Id
@Column (name = "UUID")
UUID id;
VehicleType type
(getters, setters, other values, etc.)
}
enum VehicleType {
TRUCK,
TRAILER,
OTHER;
}
and my DB part has two tables - one for vehicles and lookup table for vehicle types:
Vehicles
UUID VARCHAR (PK)
vehicle_type_id INT (FK to VehicleTypes)
VehicleTypes
vehicle_type_id INT (PK)
vehicle_type VARCHAR
My question is, is it possible to arrange this in the presented manner? If it is possible, how to implement it (annotations, etc.). If not, what is the best way to implement similar structure?
-----EDIT-----
I have managed to achieve my goal (more or less) using solution described by Anthony Patricio.
DB part stayed the same, while Java part looks like this:
@Entity
@Table (name = "Vehicles")
class Vehicle {
@Id
@Column (name = "UUID")
UUID id;
@Column (name = "vehicle_type_id")
@Type (type = "VehicleEnumUserType")
VehicleType type
(getters, setters, other values, etc.)
}
enum VehicleType {
TRUCK(1),
TRAILER(2),
OTHER(0);
private int value;
VehicleType(int value){
this.value = value;
}
public int getValue() {
return value;
}
public static VehicleType fromValue(int value){
for (VehicleType type : VehicleType.values()){
if (value == type.value) return type;
}
throw new IllegalArgumentException("Value not mapped by VehicleType enum");
}
}
VehicleEnumUserType implements UserType{
private static final int[] SQL_TYPES = {Types.INTEGER};
public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sharedSessionContractImplementor, Object o)
throws HibernateException, SQLException {
int number = resultSet.getInt(strings[0]);
return resultSet.wasNull() ? null : VehicleType.fromValue(number);
}
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i, SharedSessionContractImplementor sharedSessionContractImplementor)
throws HibernateException, SQLException {
if (o == null){
preparedStatement.setNull(i, Types.INTEGER);
} else {
preparedStatement.setInt(i, ((VehicleType)o).getValue());
}
}
// other mandatory methods required by UserType interface
}
This solution fits my requirements - Vehicle type is restricted both on DB side (by lookup table restriction) and on java side (by VehicleType enum). Moreover, vehicle type is stored as integer, reducing space required to store data. Last but not lest, this solution allows for quite safe addition of new Vehicle Types (e.g. problems related with EnumType.ORDINAL
).
Hope anyone finds this solution useful.
Upvotes: 3
Views: 1556
Reputation: 6574
you can use "Enumerated" annotation
@Enumerated(EnumType.STRING)
VehicleType type
Upvotes: 1