I'm use Spring Boot and trying to use #OneToOne JPA annotation . My class looks like this:
Primary Class
#Entity
public class User {
....
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id", referencedColumnName = "userID")
private ForeignProfile userForeignProfile;
}
Second Class:
#Entity
public class ForeignProfile {
#Id
private Long id;
private Long userID;
.....
#OneToOne(mappedBy = "userForeignProfile")
private User user;
}
I want no additional columns to be created and this 2 tables to be connected using 'id' from User table and userID from ForeignProfile table. I tryed a lot of combination but cant make it work. The configuration I have shown here doesn nothing. What I'm doing wrong?
I tried using this examples but they don't do what I need
https://www.baeldung.com/jpa-one-to-one
Related
I have created an Employee entity and a corresponding ProfilePicture entity:
#Entity
#Table(name = "employee")
public class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
}
#Entity
#Table(name = "profile_picture")
public class ProfilePicture {
#Id
private Long id;
#OneToOne
#MapsId
private Employee employee;
#Column(name = "image")
private byte[] image;
}
Now, I want to add a default image to my profile_picture table. I am using a MySQL database and introducing a default image seems to be a problem, since my profile_picture database entries require an association with an employee. The issue is that MapsId is trying to map the id of the associated employee to the id of my profile-picture. When there is no associated employee, this is impossible.
Does anyone have an idea how to solve this problem? I know I could create a dummy employee, but I don't want to do this. I would like to have an entry in my profile_picture table for which the employee_id column is simply null. Right now, however, this is violating some constraints. I know I will have to think of a different solution, I am just asking for ideas.
I’m using spring data and hibernate as JPA implementation with spring boot. I’m new to this.
I have an entity where I’m maintaining the mapping between two entities which already exist and entries into this mapping only come in at the time of a specific update.
#Entity
#Table(name = "song_genres")
public class SongGenres {
public SongGenres(Song song, List<Genre> genres) {
this.genres = genres;
this.song = song;
}
public SongGenres() {
// Empty constructor as required by hibernate
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "song_id")
private Song song;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "genre_id")
private List<Genre> genres;
public List<Genre> getGenres() {
return genres;
}
}
I’m trying to insert all the genre values associated with a song at once, using
SongGenres songGenres = new SongGenres(song, genres);
songGenresRepository.save(songGenres);
but this is giving an error that
java.sql.SQLException: Field 'genre_id' doesn't have a default value
and the sql logs show a single row insert
Hibernate: insert into song_genres (song_id) values (?)
How is multiple row insert in one-to-many achieved without cascade?
For now, I changed the entity definition since there isn't much difference between the two
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "chapter_id")
private Chapter chapter;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "genre_id", nullable = false)
private Genre genre;
and the save operation becomes
List<ChapterGenre> chapterGenres = new ArrayList<>();
for (Genre genre : genres) {
chapterGenres.add(new ChapterGenre(chapter, genre));
}
chapterGenreRepository.save(chapterGenres);
From this one, concluded there isn't much of a difference from spring's implementation point of view.
Although this ain't best performance mysql-wise. Would be interesting if spring data comes up with a simple single insert API.
Just define CASCADE type for your List here "List genres"
Add No of Items in list and persist main entity.
You can read more about it here
Eg:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "visitId")
private Collection<SampleData> lstSampleData;
I am developing a web project using Spring Boot, Spring Data JPA and Spring Data Rest technologies. I am able to setup everything successfully and able to get JSON of a simple POJOs. I have customized two classes to have OneToMany and ManyToOne relationship like this:-
#Entity
#Table(name="t_profile")
public class Profile {
#Id
#column(name="profile_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#JoinColumn(name = "cat_id", referencedColumnName = "category_id")
#ManyToOne(optional=false)
private Category category;
// getters and setters
}
#Entity
#Table(name="t_category")
public class Category {
#Id
#column(name="category_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#OneToMany(mappedBy="category")
private List<Profile> profile;
// getters and setters
}
http://localhost:8080/project/profiles
When I am accessing profiles using rest client; I am able to get json format with field of id, name but ManyToOne field is not coming in json, whle debugging in controller, profile list has values of category. But it is not coming in json.
Any thoughts?
you can use #RestResource(exported = false) in you ManyToOne field.
ManyToOne field will comes as a link. That is on accessing category, profile field will be listed under "_links" in JSON body like shown below:
"_links" : {
"profile" : {
"href" : "http://<host>/<baseUrl>/category/<categoryId>/profile"
}
Further to get details of profile for a given category call below api:
http://<host>/<baseUrl>/category/<categoryId>/profile
In hibernate if i do the following
class User{
#ManyToMany
private List<UserRole> roles;
}
it creates a separate table User_UserRole where there is two column (user_id and roles_id)
But i want a third column in there e.g "id" which uniquely identify each row and the id's are auto generated.
How do I Do this ???
with default behavior you cannot achieve this, but if you can create the table by yourself in the database (instead of letting hibernate doing it) and then mapping
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "User_UserRole", joinColumns = { #JoinColumn(name = "USER_ID") }, inverseJoinColumns = { #JoinColumn(name = "ROLES_ID") })
private List<UserRole> roles;
of course you will make the id column autoincrement also in the table definition.
You could do that with the following implementation
#Entity
class User{
#Id
private int id;
#OneToMany(mappedBy=role)
private List<UserRole> roles;
}
#Entity
#Table(name="USER_ROLE")
class UserRole{
#Id
private int id; <--ID you were looking for
#ManyToOne
private User user; <--User ID
#ManyToOne
private Role role; <--Role ID
}
#Entity
class Role{
#Id
private int id;
#OneToMany(mappedBy=user)
private List<UserRole> roles;
}
Trick is break ManyToMany relationship in two OneToMany pointing to the Jointable. This works !!
Also you can add another columns in the USER_ROLE table, without breaking anything
I have two table hesk_users, user as under.
#Entity
#Table(name="hesk_users")
public class UserHesk {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column
private int id;
#OneToOne
#JoinColumn(name="user_id")
private User user;
set.... get..
}
#Entity
#Table(name="user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#NotEmpty
#Column
private String firstname;
#OneToOne(mappedBy="user")
private UserHesk userHesk;
set ... get ...
}
I have hibernate query but it not working..
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user_id"));
Criteria criteria=sessionFactory.getCurrentSession().createCriteria(User.class);
criteria.add(Property.forName("id").notIn(detachedCriteria));
User user=(User)criteria.list().get(0);
System.out.println(user.getFirstname());
System.out.println("Subquery Size "+criteria.list().size());
Error for user_id filed. which can not be get because of relationship.
HQL and criteria queries always use the entity classes and properties. Never the names of the underlying tables and columns. The UserHesk class doesn't have any user_id property. It has a user property.
So the code should be
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user.id"));
or even
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.createAlias("user", "u")
.setProjection(Projections.property("u.id"));