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;
Related
I've got following two tables:
Customer
id
name
Order
id
product_name
customer_id
with a 1 to 1 relation
and java entities:
#Data
public class Customer{
#Id
private Long id;
private String name;
}
#Data
public class Order{
#Id
private Long id;
#Column("id")
private Customer customer; //i want to somehow map this
private String productName;
}
and a controller
#Controller
public class MyController{
//...
#GetMapping("/")
public String getmap(Model m){
System.out.println(repository.findAll()) //prints "nullrows" due to wrong sql statement
return "mytemplate";
}
}
my current issue is, that spring is executing following sql statement:
SELECT Order.id, Order.product_name, Customer.id, Customer.name
FROM Order LEFT OUTER JOIN Customer ON Customer.id = Order.id
what i actually want is to join on Customer.id = Order.customer_id while leaving the classes as they are i.e. the customer reference needs to stay in order.
i've tried every annotation that i could find so far and have made no progress.
EDIT:
I am not allowed to use jpa/hibernate
One workaround is to do the following:
#Data
public class Customer{
#Id
private Long id;
private String name;
}
#Data
public class Order{
#Id
private Long customerId;
private Long id;
#Column("id")
private Customer customer; //i want to somehow map this
private String productName;
}
causing this to automatically join on Customer.id = Order.customer_id
This does not look like a good fix however.
You can use #OneToOne and #JoinColumn annotations for your One-to-One relationship:
#Data
public class Customer{
#Id
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id", referencedColumnName = "id")
private Order order;
}
#Data
public class Order{
#Id
#Column(name = "id")
private Long id;
#Column(name = "product_name")
private String productName;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id", referencedColumnName = "id")
private Customer customer;
}
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 to make a one-to-one association between two Entities, but one of them must have two #Id. One is PRI another one is MUL. How must i declare composite id, and how do i need to map the classes?
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name = "ADDRESS_ID")
private Integer addressId;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
...
}
second class is mapped via #IdClass annotation
#Entity
#Table ( name = "ADDRESS" )
#IdClass(AddressKeys.class)
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Id
#Column ( name = "PERSON_ID")
private Integer idPerson;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
...
}
and the id class
class AddressKeys implements Serializable{
private Integer id;
private Integer idPerson;
//getters and setters
#Override
public int hashCode() {
...
return result;
}
#Override
public boolean equals(Object obj) {
...
}
}
So when i try to create and save a record i have a next error
Could not open sessionRepeated column in mapping for entity:
hibernateMappedModels.base1.mappedClasses.oneToOne.Address column:
PERSON_ID (should be mapped with insert="false" update="false")
java.lang.NullPointerException at
hibernateMappedModels.base1.Main.run(Main.java:45) at
hibernateMappedModels.base1.Main.main(Main.java:24
I tryed to make an Id fields unInsertable and unUpdatable, and it was working, but i need them to be insertable and updatable; Is there any possibility to do it?
I am confused by your mappings and not sure what is required other then the simple mappings below: if I am missing something then you will need to expand on your question. You are getting the error as you have mapped the column twice - once via the one-to-one and once as a simple property. Additionally, I am not sure why you require a composite key on address.
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
}
#Entity
#Table ( name = "ADDRESS" )
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
}
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.
While saving some data from the form I also need to add FK to the Record table. FK is User.Id.
I know how to save data from the input field on the form, but how can I set FK (int value) to this:
#ManyToOne
#JoinColumn(name = "id")
#Cascade({CascadeType.ALL})
private User user;
Is there some way to retrieve object which relates to logged user and make something like this: record.setUser(user)?
I've googled it but I didn't manage to find how to achive this.
This is my entity class.
#Entity
public class Record implements java.io.Serializable{
#Id
#GeneratedValue
private int recordId;
private String recordName;
private String recordComment;
private Date recordDate;
private Integer price;
#ManyToOne
#JoinColumn(name = "userId", insertable = true, updatable = false)
#Cascade({CascadeType.ALL})
private User user;
......
}
#Entity
#Table(name = "system_user")
public class User implements java.io.Serializable{
#Id
#GeneratedValue
private int userId;
#NotEmpty
#Email
private String email;
#Size(min=2, max=30)
private String name;
private String enabled;
#NotEmpty
private String password;
private String confirmPassword;
#Enumerated(EnumType.STRING)
#Column(name = "user_role")
private Role role;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user", orphanRemoval=true)
#Cascade({CascadeType.ALL})
private List<Record> records;
public void addToRecord(Record record) {
record.setUser(this);
this.records.add(record);
}
....
}
This is how I save data to DB:
#RequestMapping(value = "/protected/add", method = RequestMethod.POST)
public String addCost (#ModelAttribute("record") Record record,HttpSession session){
User user = userManager.getUserObject(userManager.getUserId(session.getAttribute("currentUser").toString()));
user.addToRecord(record);
recordService.addRecord(record);
return "redirect:/protected/purse";
}
DAO:
public void addRecord(Record record) {
sessionFactory.getCurrentSession().save(record);
}
UPDATE: problem was partially solved, code above works fine for me.
You also need to create User object and set the user object in a Record object using the below code
record.setUser(userObj);
and user foreign key will be automatically saved in database.