I have an entity called User with these fields :
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "last_name")
private String lastName;
#OneToMany(mappedBy="userId")
private List<Survey> survey= new ArrayList<>();
And the Survey entity which has :
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "SURVEY_ID")
private Long Id;
#ManyToOne
#JoinColumn(name = "user_id",referencedColumnName="user_id")
private User userId;
.....
I want one User to be have many Surveys, and each survey is related to one user.
But there is something wrong with the way I've mapped it, cuz as JSON file, when I access allUsers I get this :
[{"id":1,"name":"User","lastName":"user","email":"user#user.com","surveyData":[{"userId":{"id":1,"name":"User","lastName":"user","email":"user#user.com","surveyData": ,...... and repeats itself
So instead of getting as list the values of the survey data, I get the values of the Users information ?
Can someone help me with this ?
Your mapping is correct.
Just use #JsonManagedReference in your User class and #JsonBackReference in your Survey Class. #JsonManagedReference is the forward part of reference – the one that gets serialized normally. #JsonBackReference is the back part of reference – it will be omitted from serialization.
In the User Class:
#OneToMany(mappedBy="userId")
#JsonManagedReference
private List<Survey> survey;
In the Survey Class:
#ManyToOne
#JoinColumn(name = "user_id",referencedColumnName="user_id")
#JsonBackReference
private User userId;
I have 2 remarks:
If the surveys are not ordered, you can consider to use a Set instead of a List.
I would also recommend to rename the class variable userId in the Survey class to user, since it is a User object and no identifier.
Related
I am using Postgresql via Hibernate, there are three tables: users, products, user_products. Here are their mappings
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
#NotBlank
private String name;
#OneToMany(cascade = CascadeType.ALL)
private List<Products> product;
}
#Entity
public class Product{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
#NotBlank
private String name;
#Column(nullable = false)
private Integer price;
}
i know that i can get user by id, then update its field "products" and than save user back. But is it possible to do all this stuff by one request via Hibernate (or using raw sql query)?
I would create a separate Entity UserProduct and save it.
Is there some reason this won't work?
I have 3 tables which are Person Login and Account.
Person and Login is OneToOne relation and Login has one FK which is connected Person's id column called PERSON_ID.
Person(one) and Account(many) is OneToMany relation and Account has one FK which is connected Person's id column called PERSON_ID as well .
what i want to do is when i delete one data from Account , nothing happen to Person and Login.
if i delete one data from Person which id=1, Login's PERSON_ID=1 data will be deleted , and all of the data PERSON_ID=1 from Account will be deleted as well.
if i delete one data from Login which PERSON_ID=1, Person 's id=1 data will be deleted , and all of the data PERSON_ID=1 from Account will be deleted as well.
how should i set the cascade ?
i've tried dozens of times and still can't find the logic in there, thanks!!
here's my code of all 3 tables without setting cascade:
`
#Entity
#Table(name = "PERSON")
public class Person {
#Id
#Column(name = "ID", nullable = false, unique = true)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "NAME")
private String name;
#Column(name = "SEX")
private String sex;
#OneToMany(mappedBy = "person",fetch = FetchType.LAZY)
private List<Account> account;
#OneToOne(mappedBy = "person")
private Login login;
#get..
#set..
}
`
#Entity
#Table(name = "ACCOUNT")
public class Account {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "ACCOUNT")
private String account;
#Column(name = "AMOUNT")
private String amount;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PERSON_ID",referencedColumnName = "ID")
public Person person;
#get..
#set..
}
`
#Entity
#Table(name = "LOGIN")
public class Login {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private long id;
#Column(name = "USERNAME")
private String userName;
#Column(name = "PASSWORD")
private String password;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PERSON_ID", referencedColumnName = "ID")
private Person person;
#get..
#set..
}
It's been a while, but if I'm not mistaken you need to use the cascade=REMOVE option on the OneToMany and OneToOne relationships. In the OneToOne I think you need to specify cascade=REMOVE on the side that does NOT own the relationship, that is, the side that also contains the "mappedBy" property.
Finally, I believe JPA will NOT automatically load lazy relationships and then cascade them. I'm thinking you may need to fetch the relationship before you delete the parent entity (otherwise JPA will not know what to delete).
I'm trying to persist an Entity that has a Map as one of its values. To be more precise. I have the #Entity Request that have a compound primary key with three elements. This primary key is composed by an id, the User an Map<EntityType, List<EntityType>> where the first EntityType is the selected service and the related value is the list of the items where the service will be applied to.
Below the code that I have but I'm missing the annotation that i have to use for the Map. I read online that the good way to go is the create a wrapper entity like to one that i created (SelectedService2MyItem) that holds the list and then the map is just a key-value pair between two entity but I can't make it works and I don't know how to proceed.
Does anyone can help me?
Request Entity
#Entity
public class Request {
#EmbeddedId
private RequestId id;
#Column
private String name;
#ManyToOne
#JoinColumn(name = "user_id", foreignKey = #ForeignKey(name = "FK_user_id"), nullable=false)
private User user;
//Getter, setter, constructor omitted
}
RequestId
#Embeddable
public class RequestId {
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", foreignKey = #ForeignKey(name = "FK_user_id"), nullable=false)
private User user;
private Map<ServiceOffered, SelectedService2MyItem> service2MyItem = new HashMap<ServiceOffered, SelectedService2MyItem>();
//Getter, setter, constructor omitted
}
SelectedService2MyItem
#Entity
public class SelectedService2MyItem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#OneToMany(mappedBy = "id")
private List<MyItem> myItemsSelected;
//Getter, setter, constructor omitted
}
I'm creating rating system for simple web application that allows users to post text, similiar to twitter's wall. I've got two entities:
First one:
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true)
private String login;
private String hashPassword;
private String name;
private String surname;
#Column(unique = true)
private String email;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "connectedUser", fetch = FetchType.EAGER)
private List<Post> userPosts = new ArrayList<>();
Second one:
#Entity
#Table(name = "post")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String text;
#NotNull
private LocalDateTime postDate;
#ManyToOne(optional = false)
#JoinColumn(name = "user_id")
private User connectedUser;
And I'm trying to figure out, where/how to add something responsible for rating. Every single post can be rated once per user (Plus or minus) and total sum of rate should be displayed nearby. It seems simple, I need separate table in database with user_id, post_id, and rate, but how could I do that in Hibernate (Hibernate creates database by itself)? Is there any simple solution for this?
If you need additional table - you need additional Entity.
For storing the user actions related to post:
#Entity
#Table(name = "user_post_rate")
public class UserPostRate {
#OneToMany
private Post post;
#OneToOne
private User user;
private boolean upvote;
// ...
}
It could be just boolean value if you have two fixed actions related to the post. You can replace it with some integer values, let's say, for example if privileged user can upvode it for + n, or user can upvote it again after some time and etc.
However you still need sum of rated values to be stored somewhere (not to calculate it time after time).
The overall post score is not a good place to be stored in the same table when user-post related actions are stored, because you will keep many unnecessary duplicates here (until you'll need to keep track of post score history). You can store it in Post entity, because the score of the post is part of its state:
#Entity
#Table(name = "post")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
// skipped
private long score;
}
Every time a user will rate the post, update for the post entity score should be triggered.
I am very new to hibernate and I am working with JPA and Hibernate4. Trying to insert parent object in child as onetoone relationship.
I went through some tutorials but All the example in the web shows, inserting both parent and child tables.
I want to insert data in child table only.
I have two tables called user and department.
User table consists of user details with department as onetoone relationship, as follows,
#Entity
#Table(name = "User")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "_id")
private String id;
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "departmentId")
private Department departmentId;
// getters and setters...
}
Below is my Department entity,
#Entity
#Table(name = "Department")
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "_id")
private String id;
#Column(name = "name")
private String name;
// getters and setters...
}
In department table there is only 4 data. I want to insert data only in user data while insert into it and don't want to insert in Department.
How can I do that.Please assist.
You have to use mappedBy for this, as mentoned below in child Table, Department in your case
#OneToOne(mappedBy="department")
private UserEntity user;
These posts explain you better this,
JPA JoinColumn vs mappedBy
Understanding mappedBy annotation in Hibernate
You need to specify the relationship owner using mappedBy property in the OneToOne mapping in the owner side, here in your case in the Department class, you should add:
#OneToOne(mappedBy="department")
private UserEntity user;
I updated your code, to included the stated annotation and also renamed the Department property in your UserEntity class from departmentId to department to avoid confusion between relationship owner and its id:
#Entity
#Table(name = "User")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "_id")
private String id;
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "departmentId")
private Department department;
// getters and setters...
}
Below is the Department entity,
#Entity
#Table(name = "Department")
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "_id")
private String id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy="department")
private UserEntity user;
// getters and setters...
}
This will give you the right mapping with the expected behaviour.
In the #OneToOne annotation, the default value for parameter optional is true. So your annotation is the same as #OneToOne(fetch = FetchType.EAGER, optional = true). This means you can simply leave the Department in a UserEntity instance empty. In that case, persisting it results in persisting only a user entity and no department.
Even if you created a Department instance and assigned it to a UserEntity instance, persisting the UserEntity would not automatically persist the Department, since you don't have any cascade parameter in your annotation. If you don't automatically cascade persists, you would have to persist the Department first and then persist the corresponding user entity.
Maybe you're asking about using existing departments for your user entities. In that case, you first need to get the department via Hibernate (or the JPA API) from an entity manager. The entity instance you get is managed by Hibernate, and you can then set it in a UserEntity and persist that, to have it refer to the department.
Finally, I think one department will probably have more than one user. It might make more sense to have a #ManyToOne annotation instead of #OneToOne, indicating multiple users can refer to the same department, but that depends on your domain model.