How to map a nested Collection in Hibernate projection - java

There are two entities:
#Data
#Entity(name = "user")
public class User {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
#Column(name = "username")
private String username;
#ToString.Exclude
#EqualsAndHashCode.Exclude
#OneToMany(mappedBy = "user")
private Collection<Address> addresses;
...
}
#Getter
#Setter
#Entity(name = "address")
public class Address {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
#Column(name = "address")
private String address;
#ManyToOne
#JoinColumn(name = "user_id")
private WebTutorUser user;
...
}
it is needed to create a projection like this to return a list of objects with each one has users username and a list of addresses:
public interface UserProjection {
String getUsername();
List<Address> getAddresses();
}
and call it in a repository
List<UserProjection> findBy();
but it doesn't return addresses list

Just need to create a nested projection:
public interface UserProjection {
String getUsername();
List<AddressProjection> getAddresses();
interface AddressProjection {
String getAddress();
}
}
and it is possible to call it in a repository like that:
List<UserProjection> findBy();
or
#Query("select u.username from user u left join fetch u.addresses")
List<UserProjection> findBy();

Related

Enum values are not saved in the database(PostgreSql)

The issue is that the enum values are not being saved in the database, so whenever I register new user it returns user with 0 role size even though I have all the right configurations, so came to the root cause which is enum values of ERole not being saved in the database and the Role table is empty.
ERole enum:
public enum ERole {
ROLE_USER,
ROLE_MODERATOR,
ROLE_ADMIN
}
Role entity:
#EqualsAndHashCode
#NoArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "roles")
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Enumerated(EnumType.STRING)
#Column(length = 20)
private ERole role;
#ManyToMany(mappedBy="roles")
private List<User> users = new ArrayList<>();
public Role(ERole role) {
this.role = role;
}
}
User entity:
#Getter
#Setter
#NoArgsConstructor
#EqualsAndHashCode
#Entity
#Table(name = "users",
uniqueConstraints = {
#UniqueConstraint(columnNames = "name"),
})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String pass;
#JsonIgnoreProperties("users")
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_roles",
joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") })
private List<Role> roles = new ArrayList<>();
public User(String name, String pass) {
this.name = name;
this.pass = pass;
}
}
As you see below in the diagram Role entity has the role column with ERole type
I have seen the oter similar threads where it is suggested to use the #Enumerated(EnumType.STRING) which I've been using in the first place.

Why JpaRepository<User, Long> returns null value

I have a Spring Boot project, in which I have problem with JpaRepository<User,Long>.
I defined following interface
public interface UserDAO extends JpaRepository<User, Long> {
User findByEmail(String email);
}
which was implemented in UserServiceImpl
#Override
public User findByEmail(String email) {
return userDAO.findByEmail(email);
}
and I need it in UserDetailsServiceImpl but next line
User user = userDAO.findByEmail(email);
returns null.
My model classes:
User
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "email")
private String email;
#Column(name = "login")
private String login;
#Column(name = "password")
private String password;
#ManyToMany
#JoinTable(name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
#Transient
private String confirmPassword;
//getters-setters
}
Role
#Entity
#Table(name = "roles")
public class Role implements GrantedAuthority {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "name")
private String name;
#ManyToMany(mappedBy = "roles")
private Set<User> users;
What can I do?
You need to follow JavaBean specification for entity(you need to have default contrucor and getters and setters in User and Role)
Try to use the annotations on the getter, not the fields.

How to access data in bidirectional many to many mapping

UserDetail.java (model class)
#Entity
public class UserDetail {
#Id
private String email;
private String name;
private String password;
#ManyToMany(cascade = CascadeType.ALL)
private List<Role> role;
#ManyToMany(cascade = CascadeType.ALL,mappedBy = "user")
private List<GroupDetail> group;
}
GroupDetail.java ( model class)
#Entity
public class GroupDetail {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(unique = true)
private String groupName;
#ManyToMany(cascade = CascadeType.ALL)
private List<UserDetail> user;
#ManyToMany(cascade = CascadeType.ALL)
private List<Role> role;
}
Here as you can see GroupDetail is the owner of the association and Hibernate will only check that side when maintaining the association.
So, how do i get List of GroupDetail using the user email?
Following should work for you:
select userDtl.group from UserDetail userDtl where userDtl.email = 'Your Email'
If this does not work, then you could try to use join explicitly like this:
select g from UserDetail u join u.group g where u.email = 'Your Email'
Do this, add getter and setter in both entities.
UserDetails user = em.find(UserDetails.class, emailId);
List<GroupDetail> group = user.getGroup();

Fetch all children as a list with Spring Data JPA using projection

I want to use projections to fetch only specific fields from my database with Spring Data JPA.
This is my (shortened) data model:
#Entity
#Table(name = "data")
#Data
public class DataEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String description;
#LazyCollection(LazyCollectionOption.FALSE)
#Fetch(value = FetchMode.SUBSELECT)
#OneToMany(mappedBy = "data", fetch = FetchType.LAZY)
#Builder.Default
private List<OwnerEntity> owners = new ArrayList<>();
}
#Entity
#Table(name = "owner")
#Data
public class OwnerEntity {
#EmbeddedId
public OwnerId id = new OwnerId();
#Fetch(value = FetchMode.JOIN)
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="userId", insertable = false, updatable = false)
private UserEntity user;
#ManyToOne
#JoinColumn(name="dataId", insertable = false, updatable = false)
private InterfaceEntity iface;
}
#Embeddable
#Data
public class OwnerId implements Serializable {
private Integer dataId;
private String userId;
}
#Entity
#Table(name = "users")
#Data
public class UserEntity {
#Id
private String id;
private String name;
private String mail;
}
This is my projection:
public interface DataProjection {
String getName();
String getDescription();
List<UserEntity> getOwners();
}
Finally, this is my DAO:
public interface DataDao extends CrudRepository<DataEntity, Integer> {
#Query("select d.name as name, " +
" d.description as description, " +
" o.user as owners " +
"from DataEntity d " +
"left join d.owners o " +
"order by d.name")
List<DataProjection> getData();
}
It generally works but it returns one row for each owner resulting in multiple same DataProjections with a list containing only one of the owners.
A similar problem was mentioned in this question but as mentioned in the solutions comments this would make it an open projection loading all columns.
Is there a solution other than mapping the resulting rows programmatically?

many-to-many-relationship between two entities in spring boot

I have two Entities in my Spring-Boot Application:
User.java
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String firstname;
String lastname;
String username;
String password;
}
and
Role.java
Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
String description;
}
for my MySql database
I have excluded the getter and setter methods for this question.
I want to realise a Many-to-Many-Relationship between both Entities. Every user should be able to assign multiple roles to himself
I already Created a mapping table for both tables in my database. It has the rows
user_id
role_id.
I also created a new Entity UserRole.java which looks like this:
#Entity
#Table(name = "user_role")
public class UserRole implements Serializable{
private User user;
private Role role;
#Id
#ManyToOne
#JoinColumn(name = "user_id")
public User getuser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Id
#ManyToOne
#JoinColumn(name = "role_id")
public Role getrole(){
return role;
}
public void setRole(Role role){
this.role = role;
}
}
Now my question: is this construction correct? If yes, how do i add existing roles to an existing user and get the roles of this user in spring-boot?
You can find any tutorial connected with many-to-many relationship using Hibernate/Spring Data, example:
Spring Data many-to-many
With your model it's simple to add the relationship mappings, like this:
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable
private Set<User> users;
}
and this:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
private String username;
private String password;
#ManyToMany(mappedBy = "users")
private Set<Role> roles;
}

Categories

Resources