I am developing an application using Spring and Hibernate. Below are my model bean classes:
Employee
#Entity
#Table(name="employee")
public class Employee {
#Id
#Column
#GeneratedValue
private int empid;
#Column
private String firstName;
#Column
private String lastName;
#Column
private String email;
#Column
private String password;
#Column
private boolean isAdmin;
#Column
private boolean isActive;
#Column
private boolean isLocked;
//getter and setter
PersonalDetails
public class PersonalDetails {
#Column
#Id
private int empid;
#Column
private String personalEmail;
#Column
private String mob;
#Column
private String permenantAdress;
#Column
private String currentAddress;
#Column
private String gender;
#Column
private String maritialStatus;
#OneToOne
#PrimaryKeyJoinColumn
#ForeignKey(name="empid")
private Employee employee;
//getter and setter
My tables get created automatically on the server startup but foreign key constraint in PersonalDetails table is not getting set.
Did I missed anything here?
I think your #OneToOne mapping should be as follows:
#MapsId
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "empid", referencedColumnName = "empid")
private Employee employee;
The cascade attribute is optional, but a good practice.
Related
User class
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="PK_USER_ID")
private Integer userId;
#Column(name="FIRST_NAME")
private String firstName;
#Column(name="LAST_NAME")
private String lastName;
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
#JoinColumn(name="FK_USER_ID",referencedColumnName="PK_USER_ID")
private Set<DeviceInfo> deviceInfos;
}
DeviceInfo
#Entity
#Table(name="device_info")
public class DeviceInfo {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="DEVICE_ID")
private Integer deviceId;
#Column(name="DEVICE_KEY")
private String deviceKey;
#Column(name="FK_USER_ID")
private Integer userId;
}
When i try to insert data into user table and device_info table, data is inserted but foreign key column of device_info table not updated with primary key of user table.
Hibernate version:4.3.6.Final
Spring version :4.3.1
Have you missed setting user Object in deviceInfo object before persisting, code should look like:
user.setDeviceInfo(setOfDeviceInfo);
deviceInfo.setUser(user);
session.save(user);
I think #ManyToOne mapping is missing in your entity DeviceInfo
User.java
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="PK_USER_ID")
private Integer userId;
#Column(name="FIRST_NAME")
private String firstName;
#Column(name="LAST_NAME")
private String lastName;
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY, mappedBy = "user")
private Set<DeviceInfo> deviceInfos;
}
DeviceInfo.java
#Entity
#Table(name="device_info")
public class DeviceInfo {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="DEVICE_ID")
private Integer deviceId;
#Column(name="DEVICE_KEY")
private String deviceKey;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PK_USER_ID", nullable = false)
private User user;
}
I have a many to many mapping: users and rooms, as follow:
User.java
#Entity
#Table(name="users", indexes = {
#Index(unique=true, columnList="uid"),
#Index(unique=true, columnList="backendAccessToken"),
#Index(columnList="backendAccessToken", name="idx_backend")
})
public class User extends BasePersistable {
private static final long serialVersionUID = 1492535311821424305L;
#Column(nullable=false, unique=true)
private String nickname;
#Column(nullable=false)
private Integer uid;
#Column(nullable=false)
private String backendAccessToken;
#Column
private String name;
#Column
#JsonIgnore
private String email;
#Column
private String location;
#Column
private String company;
#Column
private String avatar;
#Column
#JsonIgnore
private String accessToken;
#CreationTimestamp
private Date memberSince;
#ManyToMany(targetEntity=Room.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE })
#JoinTable(name="room_users",
joinColumns={ #JoinColumn(name="user_id") },
inverseJoinColumns={ #JoinColumn(name="room_id") })
private List<Room> rooms = new ArrayList<>();
Room.java
#Entity
#Table(name="rooms", indexes = {
#Index(unique=true, columnList="uid"),
#Index(columnList="uid"),
#Index(columnList="fullName")
})
public class Room extends BasePersistable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(nullable=false)
private Integer uid;
#Column(nullable=false)
private String name;
#Column(nullable=true)
private String fullName;
#Column(nullable=false)
#Lob
private String description;
#Column(nullable=true)
private String homepage;
#Column(nullable=false)
private String owner;
#ManyToOne
private Organization organization;
#OneToMany(mappedBy="room")
#JsonIgnore
private List<Message> messages = new ArrayList<>();
#ManyToMany(mappedBy="rooms", targetEntity=User.class)
#JsonIgnore
private List<User> users = new ArrayList<>();
#Column(name="private")
private Boolean _private = false;
And when I try to create the schema, I'm seeing this error:
A Foreign key refering com.models.Room from com.models.User has the wrong number of column. should be 2
I did some research, tried to use JoinColumns annotation on User and didn't worked.
EDIT
I found the error: the class BasePersistable already defined the id. So I removed the id from Room and it worked. Thanks for the tip Mateusz Korwel and kakashihatake
I can't make my foreign keys auto generate using hibernate and jpa with annotations. Everything seems ok, The entries are saved in database. All the date come from one form which, when submited creates an User object with ModelAttribute and then saves it in Database.
Here are my beans. Anything else i should add ?
#Entity
#Table(name="adress")
public class Adress implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="adress_id")
private Integer adressId;
#NotBlank(message="The city must be completed")
#Column(name="city")
#Size(min=5,max=30)
private String city;
#NotBlank(message="The street must be completed")
#Column(name="street")
#Size(min=5,max=30)
private String street;
#NotNull(message="The street number must be completed")
#NumberFormat
#Column(name="street_no")
private Integer streetNo;
#OneToOne
#JoinColumn(name="user_id")
private User user;}
and the other one:
#Entity
#Table(name="users")
public class User implements Serializable {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;
#NotBlank(message="Username can't be blank")
#Size(min=5,max=30)
#Column(name="username")
private String username;
#NotBlank(message="Password field can't be blank")
#Size(min=5,max=30)
#Column(name="password")
private String password;
#NumberFormat
#NotNull(message="Age field must not be blank")
#Column(name="age")
private Integer age;
#Column(name="message")
#Size(min=0,max=100)
private String message;
#Column(name="date")
#DateTimeFormat(pattern="dd/mm/yyyy")
private Date dateCreated;
#OneToOne(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Adress adress;
+getters and setters for them
public void save(T entity){
sessionFactory.getCurrentSession().save(entity);
}
If I understand you correctly and you're trying to get Hibernate to set the foreign key on your related record this might help. Try getting rid of mappedBy and instead specify the JoinColumn. This works for me on a one to many:
The order:
#Entity
#Table(name = "`order`")
public class Order implements Serializable {
#Id
#GeneratedValue
private Long id;
// Order columns...
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private Set<Item> items;
}
The item:
#Entity
#Table(name = "item")
public class Item implements Serializable {
#Id
#GeneratedValue
private Long id;
// Item columns...
#ManyToOne(optional = false)
#JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
private Order order;
}
in adress class
#OneToOne(mappedBy="adress")
private User user;
and in user class
#OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER,optional=false)
#PrimaryKeyJoinColumn
private Adress adress;
Hibernate novice here, running into issues trying to properly map the relationships between my Hibernate Entity classes.
I have a Ticket Entity and a User Entity. A user has many tickets, but a ticket only belongs to one unique user. What i've done is mapped the User - Tickets as a #OneToMany relationship and the Tickets - User as a #ManyToOne relationship. However, I am not getting any tickets returned.
The Query Hibernate is running is:
Hibernate: select tickets0_.user_user_id as user1_1_3_, tickets0_.tickets_ticket_id as tickets2_3_, ticketenti1_.ticket_id as ticket1_0_0_, ticketenti1_.assigned_to_user_id as assigned7_0_0_, ticketenti1_.belongs_to_user_id as belongs8_0_0_, ticketenti1_.date_created as date2_0_0_, ticketenti1_.description as descript3_0_0_, ticketenti1_.status_id as status4_0_0_, ticketenti1_.title as title0_0_, ticketenti1_.urgency_id as urgency6_0_0_, userentity2_.user_id as user1_1_1_, userentity2_.email as email1_1_, userentity2_.firstname as firstname1_1_, userentity2_.lastname as lastname1_1_, userentity2_.password as password1_1_, userentity2_.role_id as role6_1_1_, userentity2_.username as username1_1_, userentity2_.verified as verified1_1_, userentity3_.user_id as user1_1_2_, userentity3_.email as email1_2_, userentity3_.firstname as firstname1_2_, userentity3_.lastname as lastname1_2_, userentity3_.password as password1_2_, userentity3_.role_id as role6_1_2_, userentity3_.username as username1_2_, userentity3_.verified as verified1_2_ from user_ticket tickets0_ inner join ticket ticketenti1_ on tickets0_.tickets_ticket_id=ticketenti1_.ticket_id left outer join user userentity2_ on ticketenti1_.assigned_to_user_id=userentity2_.user_id left outer join user userentity3_ on ticketenti1_.belongs_to_user_id=userentity3_.user_id where tickets0_.user_user_id=?
The Entity Classes are:
TicketEntity.java
#Entity
#Table(name="ticket")
public class TicketEntity {
#Id
#Column(name="ticket_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="date_created")
#Temporal( TemporalType.TIMESTAMP )
private Date date_created;
#Column(name="status_id")
private int status_id;
//private TicketStatus status;
#Column(name="urgency_id")
private int urgency_id;
#ManyToOne
#JoinColumn(insertable=false, updatable=false)
private UserEntity belongs_to;
#ManyToOne
#JoinColumn(insertable=false, updatable=false)
private UserEntity assigned_to;
UserEntity.java
#Entity
#Table(name="user")
public class UserEntity {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="firstname")
private String firstname;
#Column(name="lastname")
private String lastname;
#Column(name="username")
private String username;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Transient
private String confirmpassword;
#Column(name="verified")
private boolean verified;
#Column(name="role_id")
private int role_id;
#OneToMany(fetch = FetchType.EAGER)
private List<TicketEntity> tickets;
Any help is appreciated,
Thanks!
In UserEntity.java, you need to add "mappedBy" for List<TicketEntity> tickets, like this:
#OneToMany(fetch = FetchType.EAGER, mappedBy="belongs_to")//why you have two UserEntity in TicketEntity.java?
private List<TicketEntity> tickets;
In TicketEntity.java, add (name = "user_id") to #JoinColumn for UserEntity belongs_to, like this:
#ManyToOne
#JoinColumn(name = "user_id", insertable=false, updatable=false)
private UserEntity belongs_to;
Same for private UserEntity assigned_to. You may need add another list for it in UserEntity.java if you want to query it too.
This is my entity class Author
#Entity
#Column(name = "ID")
private Long id;
#Column(name = "LAST1")
private String last;
#Column(name="FIRST1")
private String first;
#Lob
#Column(name = "BIO")
private String bio;
#OneToOne
private AuthorDetail authorId;
getters and setters & zero parameter constructor
this is my other entity AuthorDetail here i have mapped using #OneToOne(optional = false,mappedBy = "authorDetail")
#Column(name = "ID")
private Long id;
#Column(name = "ADDRESS1")
private String address1;
#Column(name="ADDRESS2")
private String address2;
#Column(name = "CITY")
private String city;
#Column(name = "STATE1")
private String state;
#Column(name = "ZIP")
private String zip;
#Column(name = "START_DATE")
#Temporal(TemporalType.DATE)
private Date startDate;
#Lob
#Column(name = "NOTES")
private String notes;
#OneToOne(optional = false,mappedBy = "authorDetail")
private Author authorId;
getters and setters
this my main class
`EntityTransaction entr=em.getTransaction();
entr.begin();
Author author=new Author();
author.setFirst("MD");
author.setLast("RAHMATH");
author.setBio("A Software Developer");
Set detailSet=new HashSet<AuthorDetail>();
AuthorDetail detail=new AuthorDetail();
detail.setAddress1("Address1");
detail.setAddress2("Address2");
detail.setCity("NoMansLand");
detail.setState("ZZ");
detail.setZip("12345");
detail.setNotes("This is test detail");
detailSet.add(detail);
em.persist(author);
entr.commit();`
i am getting exceptions if i try run the program
If you want a single-directional relation, you don't need to write #OneToOne in both class.
From the given piece of code, it appears that you want the bi-direction relationship between Author detail and Author.
For the other side to be aware of the relation (bidirectional), it is required to add the mappedBy attribute to the #OneToOne annotation. This attribute references the (Java) property in the entity that is the owner of the relationship. In your case, in AuthorDetail class you need to add;
#OneToOne(optional = false,mappedBy = "authorId")
private Author authorId;
In mappedBy property, you need to give reference to the entity not class name.
In your Author change the following:
#OneToOne
private AuthorDetail authorId;
To:
#OneToOne
private AuthorDetail authorDetail;