I have a problem while building a OneToMany relationship between two entities. I have a user who can have multiple Properties. I want to define this relationship and create tables in MySql however when I run it it gives me Exception in thread "main" java.lang.NullPointerException
at start.ApplicationStart.main(ApplicationStart.java:44)
and also there are 2 more columns in the user table in mysql "user_id" and city. Now what I defined so far in my code is:
in class user I have the following fields:
#Id
private String id;
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL) //mapped by variable in class user
private List<Properties> properties;
and in class Properties I have:
#Column(name = "city")
private String city;
#Column(name = "address", nullable = false)
private String address;
#ManyToOne
#JoinColumn(name="user_id")// , nullable=false
private User user;
I don't understand why I have the extra columns in the user table. Also I am using entity manager for both tables. Any hint would be great
Related
Lets say if I have two entities like this,
Users Entity:
public class Users {
#Basic
#Column(name = "USER_NAME")
private String name;
#Basic
#Column(name = "USER_ADDRESS")
private String address;
#ManyToOne
#JsonBackReference
#JoinColumn(name = "PERSON_ID")
private Person personData;
}
Person Entity:
public class Person {
#Id
#Column(name = "PERSON_ID")
private Long personId
#Basic
#Column(name = "USER_ADDRESS")
private String address;
#OneToMany(mappedBy="personData", cascase = CascadeType.ALL, orphanRemoval = true)
#JsonManagedReference
List<Users> users;
}
Now, how do I create DTOs for these two entities when I am doing unit testing? Also, when I try to access these entities in my service, it gives me StackOverflow Exception because of nested entities.
When I try to access these entities in my service, it
gives me StackOverflow Exception because of nested entities.
This should have been the case before you have added the annotations #JsonManagedReference and #JsonBackReference. If the SO error continues with those annotations then there is some other issue with your entities and not related with those nested fields.
Now, how do I create DTOs for these two entities when I am doing unit
testing?
The same way you have your now entities but you do one of the following:
You place again the annotations #JsonManagedReference and #JsonBackReference on those DTOs same way you have them in your entities.
You break the relationship into a one sided relationship. So for example UsersDto does not have a field of personData or PersonDto does not have the List<UsersDto> users.
However DTOs usually bring some more functionality in the table in order to consider using them. Just such small issue of stack overflow could be easily avoided only with the above annotations directly on entities.
I want to have hibernate generate some tables with foreign keys and so on. Ill give you an example of the query i want hibernate to generate:
create table RealtimeCost(id INTEGER not null primary key Autoincrement,
mnemonic varchar(50)not null references Exchange(mnemonic),
sid int not null references License(sid),
price numeric(10,2) not null)
so this query should be generated by hibernate via Annotations. The corresponding class to this is:
#Entity
#Table
public class RealtimeCost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#MapsId("mnemonic")
#JoinColumn(referencedColumnName="sid")
private String mnemonic;
#MapsId("sid")
#JoinColumn(referencedColumnName="sid")
private Integer sid;
#Column
private Double price;
Example for what the mnemonic in RealtimeCost should be mapped to (each mnemonic in RealtimeCost has exactly 1 value in Exchange):
#Entity
#Table
public class Exchange {
#Id
#Column(name="mnemonic")
private String exchange;
#Column
private String description;
As you can see I've tried a bit with the help of the docs, but I was not able to have the foreign keys be generated by hibernate. It would be really kind, if anyone could tell me the needed annotations and values for this class, so i can do it myself for the other classes as well. Also please tell me if i need to change anything in the Exchange class for the mapping to work. Thanks in advance
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "accommodation_type", unique = true, nullable = false)
private AccommodationType accommodationType;
#ManyToOne()creates a relationship according to #JoinColumn()
name in #JoinColumn() is the table name that you want to make a connection.
Then when you create a class that is going to be connected to main class, you first need to give it a table name below #Entity e.g #Table(name="accommodation_types")
Then you create your variable.
//bi-directional many-to-one association to Accommodation
#OneToMany(mappedBy="accommodationType", fetch=FetchType.EAGER)
private List<Accommodation> accommodations;
value of mappedByis the variable name in main class.
I'm not an expert but we let hibernate do all the work with the javax.persistence annotations for joining entities.
#javax.persistence.ManyToOne( fetch = javax.persistence.FetchType.EAGER, optional = true )
#javax.persistence.JoinColumn( name = "VIEWTYPE_ID", nullable = true, unique = false, insertable = true, updatable = true )
private com.company.other.subproject.ViewType viewType;
Maybe this is what you need. Since this let's hibernate care about the tables that have to be created or not and the foreignKeys get created automatically with the dialect of the database you communicate with.
You should set up the association in one entity and use the mappedBy in the other. You don't need #MapsId because you are not using embedded entities (read the docs). Take a look at the #OneToMany and #ManyToOne relationships:
#Entity
#Table
public class RealtimeCost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany
#JoinColumn(name="mnemonic")
private Exchange exchange;
...
}
#Entity
#Table
public class Exchange {
#Id
#Column(name="mnemonic")
private String mnemonic;
#Column
private String description;
#ManyToOne(mappedBy="exchange")
private RealtimeCost realtimeCost;
...
}
Every answer posted here got an upvote from me, because everyone was kinda right, but it was not 100% what i was searching for, yet it helped me solving my problem by myself. For the example i posted, the solution i was seeking is as follows (i also added not nullable):
#Entity
#Table
public class RealtimeCost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
#JoinColumn(name = "mnemonic",nullable=false)
private Exchange exchange;
#ManyToOne
#JoinColumn(name = "sid",nullable=false)
private License license;
#Column(nullable=false)
private Double price;
these are the annotations i was seeking for RealtimeCost class. I did not need any special annotations in Exchange class. #Nico answer was closest to what i need, therefore his answer will be accepted
I'm using JPA Hibernate/Spring boot to build a web server with MySQL database, and I'm trying to extend a POJO Entity that looks like this, with additional OneToMany Lists.
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private String name;
....Constructors, getters and setters....
}
with this basic user entity, I just wanna make a UserInfo entity with additional information about the user's careers.
#Entity
public class UserInfo extends User {
#OneToMany(cascade= CascadeType.ALL, fetch= FetchType.EAGER)
#JoinColumn(name="user_id", referencedColumnName = "id")
private List<Career> careers;
....Constructors, getters, setters......
}
And I'm quite confused which inheritance strategy I should choose. I don't think its necessary to make another column or table for this.
Or should I just query twice..?
I'm kinda new to JPA so not sure which is considered as the best practice or design..
Edit:
This is how Career entity looks like. Just in case..
#Entity
#Table(name="career")
public class Career {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private Integer user_id;
#Column(nullable=false)
private String name;
#Column(nullable=false)
private String description;
....Constructors, getters and setters....
}
Since extending User table was meaningless(just in my case), I changed the User class like this.
#Table(name="user")
public class User {
#Id
#GeneratedValue
private Integer id;
#Column(nullable=false)
private String name;
#OneToMany(fetch= FetchType.LAZY)
#JoinColumn(name="user_id", referencedColumnName = "id")
private List<Career> careers;
....Constructors, getters, setters......
}
Now I'm trying this with Spring Data JPA, and when I try to show the list of Users with their Careers, it is now querying more than 40 times taking about a minute to show the result.
Is this the N+1 problem..? how can I solve this?
In my opinion the error lies within the model itself. Why should UserInfo extend User? I cannot imagine which attributes or methods the UserInfo should inherit from a User. Typical inheritances would be "Developer" or "Administrator".
Why don't you add UserInfo as a 1:1 relation in your User entity? Another option is to omit UserInfo and put the Careers as a 1:n relation right into your User.
To prevent possible n+1 issues on a growing number of Careers you might want to change the fetch mode. See below
#OneToMany(fetch=FetchType.LAZY,mappedBy="user")
#Fetch(FetchMode.SUBSELECT)
private Set<Career> careers = new HashSet<>();
I am trying to create a column 'Barcode' which is to be the primary key and of type string.
this is what i am doing :
// for table-one
#Id
#Column(name = "BARCODE", nullable=false)
private String barcode;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "BARCODE")
private List<Doc_Mvmnt> doc_mvmnt = new ArrayList<>();
and in another where table-one will have one to many mapping
//for table-two
#ManyToOne
#JoinColumn(name = "BARCODE", nullable=false)
public String barcode;
I am recieving the exception :
Exception in thread "main" org.hibernate.AnnotationException: #OneToOne or #ManyToOne on database.Doc_Mvmnt.barcode references an unknown entity: java.lang.String
I assume your table-one object is in fact your Barcode object and it has an #Entity annotation on it.
Then, your table-two object is your Doc_Mvmnt object. The problem is that you are establishing a #ManyToOne relationship against a String object (which is not an entity, per your error). Instead, change 'String' to 'Barcode'. I also took the liberty to make it a private member, even though public should work too.
It should look like this:
//for table-two
#ManyToOne
#JoinColumn(name = "BARCODE", nullable=false)
private Barcode barcode;
I have two persistence entity: User and UserDetail. They have one-to-one relationship. I use hibernate annotations. But I am getting in my database several objects of user information for one same user. Apparently my knowledge of Hibernate annotations are not so good to solve this problem.
User class:
#Entity
#Table(name = "USER")
public class User {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "PASSWORD")
private String password;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserDetail userDetail;
// setters and getters
}
UserDetail class:
#Entity
#Table(name = "USER_DETAIL")
public class UserDetail {
#OneToOne
#JoinColumn(name = "USER_ID")
private User user;
// other fields
}
I use this in my code as follows:
UserDetail userDetail = new UserDetail();
userDetail.setInfo(info);
userDetail.setUser(seventhUser);
hibernateTemplate.saveOrUpdate(userDetail);
And everything works properly. Here's what my table USER_DETAIL:
But when I try to change user information, I get an incorrect behavior. I get following table after I again set user information:
UserDetail newUserDetail = new UserDetail();
newUserDetail.setInfo(newInfo);
newUserDetail.setUser(seventhUser);
hibernateTemplate.saveOrUpdate(newUserDetail);
Why the same two objects of information correspond to one user?? I have One-To-One relationship. How can I avoid this? What am I doing wrong?
If you want to modify an existing UserDetail, then you must set its ID, or get it from the session and modify it. Else, Hibernate thinks it's a new one that must be saved, since it doesn't have any ID.
UserDetail existingUserDetail = session.get(UserDetail.class, theUserDetailId);
existingUserDetail.setInfo(newInfo);
To make sure you don't save two UserDetail instances for the same user, you should add a unique constraint on the USER_ID column of the UserDetail database table.