Reputation: 25
So I am following a tutorial about hibernate as i want to use the framework in an upcoming project. I'm having a problem with the @ManyToOne and @OneToMay annotation and Bidirectional mapping. What i want to do is very basic stuff. I simply want two tables, one reperesenting a user, and the other one representing a vehicle. Now i want the user to be able to have many vehicles and a car should "know" the user it belongs to.
As it seems to be "best practice" to create an extra table that holds the connection between users and and vehicles. I tried to do this with the @JoinTable annotation(see below) but it is not working as i want it to.
To do this, I have coded the following classes:
UserDetails.java
@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
private String userName;
private String email;
@OneToMany()
@JoinTable(name="USER_VEHICLE", joinColumns=@JoinColumn(name="USER_ID"),
inverseJoinColumns=@JoinColumn(name="VEHICLE_ID")
)
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
...
getters and setters
vehicle.java
@Entity
public class Vehicle {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int vehicleId;
private String vehicleName;
@ManyToOne
private UserDetails user;
...
getters and setters
And class to test the above:
HibernateTest.Java
public class HibernateTest {
/**
*
* @param args
*/
public static void main(String[] args){
UserDetails user1 = new UserDetails();
user1.setUserName("testUser1");
user1.setEmail("testEmail1");
Vehicle vehicle1 = new Vehicle();
vehicle1.setVehicleName("Car");
Vehicle vehicle2 = new Vehicle();
vehicle2.setVehicleName("Jeep");
user1.getVehicle().add(vehicle1);
user1.getVehicle().add(vehicle2);
vehicle1.setUser(user1);
vehicle2.setUser(user1);
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user1);
session.save(vehicle1);
session.save(vehicle2);
session.getTransaction().commit();
session.close();
When I run this, it executes without any errors or exceptions and it creates the following tables:
USER_DETAILS
+------+----------+---------+
|userId|email |userName |
+------+----------+---------+
|1 |testEmail1|testUser1|
+------+----------+---------+
VEHICLE
+---------+-----------+-----------+
|vehicleId|vehicleName|user_userId| <- did not expect this column
+---------+-----------+-----------+
|1 |Car |1 |
+---------+-----------+-----------+
|2 |Jeep |1 |
+---------+-----------+-----------+
USER_VEHICLE
+------+----------+
|USER_ID|VEHICLE_ID|
+-------+----------+
|1 |1 |
+-------+----------+
|1 |2 |
+-------+----------+
As I understand it, the additional column "user_userId" that was created by hibernate seems to be unnecessary, as the connection between users and vehicles is already represented in the "USER_VEHICLE" table, and I did not intend to have this additional column created.
Is the way I did the bidirectional mapping wrong? And what is the right way to get this to work without the additional column being created?
Upvotes: 1
Views: 1210
Reputation: 1892
@JoinTable
is necessary if you want a @ManyToMany
relationship.
@Entity
public class UserDetails {
/* ... */
@ManyToMany
@JoinTable(name = "user_vehicle",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "vehicle_id"))
private List<Vehicle> vehicles;
}
@Entity
public class Vehicle {
/* ... */
}
USER_DETAILS VEHICLE USER_VEHICLE
+---------+ +------------+ +---------+------------+
| user_id | | vehicle_id | | user_id | vehicle_id |
+---------+ +------------+ +---------+------------+
| 1 | | 1 | | 1 | 1 |
+---------+ +------------+ +---------+------------+
Since you don't want that, you can just remove the @JoinTable
like so:
@Entity
public class UserDetails {
/* ... */
@OneToMany(mappedBy = "user")
private List<Vehicle> vehicles;
}
@Entity
public class Vehicle {
/* ... */
@ManyToOne
private UserDetails user;
}
USER_DETAILS VEHICLE
+---------+ +------------+---------+
| user_id | | vehicle_id | user_id |
+---------+ +------------+---------+
| 1 | | 1 | 1 |
+---------+ +------------+---------+
You only need a third table if you want to store additional data for a (UserDetails, Vehicle) tuple, in which case you would create a third class.
@Entity
public class UserDetails {
/* ... */
@OneToMany(mappedBy = "user")
private List<UserVehicle> vehicles;
}
@Entity
public class Vehicle {
/* ... */
}
@Entity
public class UserVehicle {
/* ... */
@ManyToOne
private UserDetails user;
@ManyToOne
private Vehicle vehicle;
@Basic
private String someString;
}
USER_DETAILS VEHICLE USER_VEHICLE
+---------+ +------------+ +---------+------------+-------------+
| user_id | | vehicle_id | | user_id | vehicle_id | some_string |
+---------+ +------------+ +---------+------------+-------------+
| 1 | | 1 | | 1 | 1 | Hello |
+---------+ +------------+ +---------+------------+-------------+
Upvotes: 1
Reputation: 1
It is normal that the column is generated. The side of the Many on a database relation have to save the FK
value.
Try to remove your @Join
annotation... Just @OneToMany
Upvotes: 0
Reputation: 1049
Try to specify relations in Vehicle
side and in User
side use mapedBy
property
Upvotes: 0