SQL Query returns Null Values - java

I have a User entity with role types Marketer, Managing Director and General Manager . When the UserRole Managing Director logs In, I want the userrole Managing Director to only see customers assigned to Usertype Marketers with the same Branch ID as the Managing Director.
I have a custom Query in the customer repository that returns a null result.
#Query("SELECT customer from Customer customer join customer.marketer marketer "
+ "where marketer.branch = :director")
List<Customer> findByUserBranch(User director);
This is the User entity
#Entity
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String firstName ;
private String lastName;
#Column(name="user_name", unique=true)
private String userName;
private String password;
private String Gender;
private String phoneNumber;
private String email;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#ManyToOne(targetEntity = Branch.class,
fetch = FetchType.LAZY )
#JoinColumn(name="branch_id")
private Branch branch;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createdDate;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<UserRole> userRole = new HashSet<>();
#Enumerated(EnumType.STRING)
private UserStatus status;
#JsonBackReference
#OneToMany(mappedBy="marketer",cascade = CascadeType.ALL, targetEntity=Customer.class)
private List <Customer> customer;
This is the controller class
#GetMapping(value="branch/customers")
public List<Customer> getListByBranch()
{ Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
User loggedInUser = userRepo.findByUserName(authentication.getName()); return customerRepo.findByBranch(loggedInUser);
}
UPDATED :
This is the Customer class
#Entity
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class Customer implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8348682056500740593L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String userName;
private String password;
private String firstName ;
private String lastName;
private String gender;
private String Address;
private String maritalStatus;
private String category;
private String motherMaidenName;
private String idType;
private String idNumber;
private String phoneNumber;
private String email;
#Column(nullable = true, length = 64)
private String photos;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dateOfBirth;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date registrationDate;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#ManyToOne(targetEntity = User.class,
fetch = FetchType.LAZY )
#JoinColumn(name="marketer_id")
private User marketer ;
#JsonBackReference
#OneToMany(mappedBy="customer_id",cascade = CascadeType.ALL, targetEntity=Investment.class)
private List<Investment> investment;

I can't make a comment, so i would ask to also give us the customer.class .

Got it resolved . I changed the User object to branch object.
#Query("SELECT customer from Customer customer join "
+ "customer.marketer marketer "
+ "where marketer.branch = :branch")
List<Customer> findByUserBranch(Branch branch);
Then refactored the controller class
#GetMapping(value="branch/customers")
public List<Customer> getListByBranch(Principal principal)
{
User loggedInUser = userRepo.findByUserName(principal.getName());
Branch branchId = loggedInUser.getBranch();
return customerRepo.findByBranch(branchId);
}

Related

How can I implement this Spring Data JPA query by method name that retrieve a specific object based on two properties?

I am working on a Spring Boot project using Spring Data JPA trying to adopt the "query by method name" style in order to define my queries into repositories.
I am finding some difficulties trying to implement a select query retrieving the list of objects based on two different "where condition". I will try to explain what I have to do.
First of all this is my main entity class named Wallet:
#Entity
#Table(name = "wallet")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Wallet implements Serializable {
private static final long serialVersionUID = 6956974379644960088L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "address")
private String address;
#Column(name = "notes")
private String notes;
#ManyToOne
#EqualsAndHashCode.Exclude // Needed by Lombock in "Many To One" relathionship to avoid error
#JoinColumn(name = "fk_user_id", referencedColumnName = "id")
#JsonBackReference(value = "user-wallets")
private User user;
#ManyToOne
#EqualsAndHashCode.Exclude // Needed by Lombock in "Many To One" relathionship to avoid error
#JoinColumn(name = "fk_coin_id", referencedColumnName = "id")
private Coin coin;
#ManyToOne
#JoinColumn(name = "type", referencedColumnName = "id")
private WalletType walletType;
public Wallet(String address, String notes, User user, Coin coin, WalletType walletType) {
super();
this.address = address;
this.notes = notes;
this.user = user;
this.coin = coin;
this.walletType = walletType;
}
}
As you can see a wallet is directly binded to a specific User object and to a specific Coin object.
For completeness this is the code of my User entity class:
#Entity
#Table(name = "portal_user")
#Getter
#Setter
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User implements Serializable {
private static final long serialVersionUID = 5062673109048808267L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name = "first_name")
#NotNull(message = "{NotNull.User.firstName.Validation}")
private String firstName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "surname")
#NotNull(message = "{NotNull.User.surname.Validation}")
private String surname;
#Column(name = "sex")
#NotNull(message = "{NotNull.User.sex.Validation}")
private char sex;
#Column(name = "birthdate")
#NotNull(message = "{NotNull.User.birthdate.Validation}")
private Date birthdate;
#Column(name = "tax_code")
#NotNull(message = "{NotNull.User.taxCode.Validation}")
private String taxCode;
#Column(name = "e_mail")
#NotNull(message = "{NotNull.User.email.Validation}")
private String email;
#Column(name = "pswd")
#NotNull(message = "{NotNull.User.pswd.Validation}")
private String pswd;
#Column(name = "contact_number")
#NotNull(message = "{NotNull.User.contactNumber.Validation}")
private String contactNumber;
#Temporal(TemporalType.DATE)
#Column(name = "created_at")
private Date createdAt;
#Column(name = "is_active")
private boolean is_active;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
#JsonManagedReference(value = "address")
private Set<Address> addressesList = new HashSet<>();
#ManyToMany(cascade = { CascadeType.MERGE })
#JoinTable(
name = "portal_user_user_type",
joinColumns = { #JoinColumn(name = "portal_user_id_fk") },
inverseJoinColumns = { #JoinColumn(name = "user_type_id_fk") }
)
private Set<UserType> userTypes;
#ManyToOne(fetch = FetchType.LAZY)
#JsonProperty("subagent")
private User parent;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
#JsonManagedReference(value = "user-wallets")
private Set<Wallet> wallets = new HashSet<>();
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
String email, String pswd, String contactNumber, Date createdAt, boolean is_active) {
super();
this.firstName = firstName;
this.middleName = middleName;
this.surname = surname;
this.sex = sex;
this.birthdate = birthdate;
this.taxCode = taxCode;
this.email = email;
this.pswd = pswd;
this.contactNumber = contactNumber;
this.createdAt = createdAt;
this.is_active = is_active;
}
}
and this is the code of my Coin entity class:
#Entity
#Table(name = "coin")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Coin implements Serializable {
private static final long serialVersionUID = 6956974379644960088L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "name")
#NotNull(message = "{NotNull.Coin.name.Validation}")
private String name;
#Column(name = "description")
private String description;
#Column(name = "code", unique = true)
#NotNull(message = "{NotNull.Coin.code.Validation}")
private String code;
#Type(type="org.hibernate.type.BinaryType")
#Column(name = "logo")
private byte[] logo;
}
Then I have this WalletRepository interface:
public interface WalletRepository extends JpaRepository<Wallet, Integer> {
}
Here I need to define a query by name method that retrieve a specific wallet of a specific User (I think that I can query by the id field of the User) and based and related to a specific Coin (I think that I can query by the id fied of the Coin).
How can I implement a behavior like this?
The following should work:
public interface WalletRepository extends JpaRepository<Wallet, Integer> {
List<Wallet> findByUserIdAndCoinId();
}
You can read more about this at:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords

Hibernate OneToOne bidirectional functionality not working

User table not saving PasswordInfo object automatically
Here are my entities
User entity
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "username")
private String userName;
#Column(name = "password")
private String password;
#Column(name = "emp_id")
private int empId;
#Column(name = "designation")
private String designation;
#Column(name = "status")
private String status;
#Column(name = "email_id")
private String emailId;
#Column(name = "account_status")
private String accountStatus;
#Column(name = "validity_date")
private Date validityDate;
#Column(name = "deactivation_date")
private Date deactivationDate;
#Column(name = "deactivated_by")
private String deactivatedBy;
#Column(name = "deactivation_remarks")
private String deactivationRemarks;
#OneToMany(fetch = FetchType.LAZY,
mappedBy = "user",
cascade = {CascadeType.PERSIST,CascadeType.MERGE,
CascadeType.DETACH,CascadeType.REFRESH})
private List<LoginDetails> loginDetails;
// add convenience methods for bi-directional relationship for LoginDetails
public void add(LoginDetails tempLoginDetails) {
if(loginDetails == null) {
loginDetails = new ArrayList<LoginDetails>();
}
loginDetails.add(tempLoginDetails);
tempLoginDetails.setUser(this);
}
#OneToOne(mappedBy = "user", fetch = FetchType.LAZY,
cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
private PasswordInfo passwordInfo;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Collection<Role> roles;
#ManyToOne(fetch = FetchType.LAZY,cascade= {CascadeType.PERSIST,CascadeType.MERGE,
CascadeType.DETACH,CascadeType.REFRESH})
#JoinColumn(name="department_id")
private Department department;
#ManyToOne(fetch = FetchType.LAZY,cascade= {CascadeType.PERSIST,CascadeType.MERGE,
CascadeType.DETACH,CascadeType.REFRESH})
#JoinColumn(name="branch_id")
private Branch branch;
/*
* TIMESTAMPS START
* */
#Temporal( TemporalType.TIMESTAMP )
#CreationTimestamp
#Column(name = "creation_date")
private Date creationDate;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updation_date")
private Date updationDate;
#ManyToOne(fetch = FetchType.LAZY,cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name="created_by")
private User createdBy;
#OneToMany(mappedBy="createdBy")
private Set<User> createdBySet = new HashSet<User>();
#ManyToOne(fetch = FetchType.LAZY,cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name="updated_by")
private User updatedBy;
#OneToMany(mappedBy="updatedBy")
private Set<User> updatedBySet = new HashSet<User>();
#PrePersist
protected void onCreate() {
creationDate = new Date();
}
#PreUpdate
protected void onUpdate() {
updationDate = new Date();
}
/*
* TIMESTAMPS END
* */
public User() {
}
// getter and setters and imports are written in real code, i have omitted them here
}
PasswordInfo entity
#Entity
#Table(name = "password_info")
public class PasswordInfo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "last_password_1")
private String lastPassword1;
#Column(name = "last_password_2")
private String lastPassword2;
#Column(name = "last_password_3")
private String lastPassword3;
#Column(name = "last_password_4")
private String lastPassword4;
#Column(name = "last_password_5")
private String lastPassword5;
#Column(name = "forced_password_flag")
private String forcedPasswordFlag;
#Column(name = "pass_count")
private int passCount;
#Column(name = "password_date")
private Date passwordDate;
#OneToOne(fetch = FetchType.LAZY,cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name="user_id")
private User user;
#Temporal( TemporalType.TIMESTAMP )
#CreationTimestamp
#Column(name = "creation_date")
private Date creationDate;
#PrePersist
protected void onCreate() {
creationDate = new Date();
}
public PasswordInfo() {
}
// getter and setters and imports are written in real code, i have omitted them here
}
This is my save method in service class
#Override
#Transactional
public String save(ReportUser reportUser) {
User user = new User();
// assign user details to the user object
user.setUserName(reportUser.getUserName());
user.setPassword(passwordEncoder.encode(reportUser.getPassword()));
user.setName(reportUser.getName());
user.setEmpId(reportUser.getEmpId());
user.setDesignation(reportUser.getDesignation());
user.setEmailId(reportUser.getEmailId());
user.setStatus(reportUser.getStatus());
user.setEmailId(reportUser.getEmailId());
user.setAccountStatus(reportUser.getAccountStatus());
user.setValidityDate(reportUser.getValidityDate());
String loggedInUser = jwtUtil.getUsername();
logger.info(">>>>> Logged In USER " + loggedInUser);
Department theDepartment = departmentDao.getDepartment(reportUser.getDepartmentId());
Branch theBranch = branchDao.getBranch(reportUser.getBranchId());
User createdByUser = userDao.findByUserName(loggedInUser);
user.setBranch(theBranch);
user.setDepartment(theDepartment);
user.setCreatedBy(createdByUser);
String[] roleArr = reportUser.getFormRole().split(",");
List<Role> roleList = new ArrayList<Role>();
for(String r: roleArr) {
roleList.add(roleDao.findRoleByName(r));
}
Collection<Role> roles = roleList;
user.setRoles(roles);
ParameterMst pmst = otherDao.getParameterValueById(1L);
int passwordExpirationDays = Integer.valueOf(pmst.getValue());
PasswordInfo pInfo = new PasswordInfo();
// Add passwordExpirationDays to current date
Date passwordExpirationDate = DateUtils.asDate(LocalDate.now().plusDays(passwordExpirationDays));
logger.info(">>>>> Password Expiration Date " + passwordExpirationDate);
pInfo.setPasswordDate(passwordExpirationDate);
pInfo.setPassCount(12);
pInfo.setUser(user);
user.setPasswordInfo(pInfo);
// save user in the database
userDao.save(user);
return user.getUserName();
}
This is save in DAO Implementation
#Override
public void save(User user) {
// get current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
currentSession.saveOrUpdate(user);
}
Due to bi-directional relationship set in User, i should be able to update both in one go, rather than doing separately.
Why this isn't working?
Please Help!
Don't use mappedBy and #JoinColumn together as they serve slightly different purposes.
See the uses of both and use either one of them.
Try removing #JoinColumn annotation from PasswordInfo entity.
Try to annotate like this
In class PasswordInfo :
#OneToOne(mappedBy = "passwordInfo")
private User user;
In class User
#OneToOne()
private PasswordInfo passwordInfo;
mappedBy say that User table is the owner of the relationship using its propertie passwordInfo.

Referencing join column in JPQL

With the query Select c from Card c join User u on c.userId=u.userId where u.username=':u', I am trying to grab a list of Cards for the User based on the username available in User the table. However, I am running into the antlr.SemanticException: could not resolve property: userId of: com.abc.SheridanSportsWAR.entity.Card exception when I run it. How do I reference the UserId column in my Card entity?
Card.java
#Entity
public class Card {
#Id
#Column(name="CardId")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer cardId;
#Column(name="CardNumber")
private String cardNumber;
#Column(name="CardType")
private String cardType;
#Column(name="ExpiryMonth")
private String expiryMonth;
#Column(name="ExpiryYear")
private String expiryYear;
#Column(name="CardHolder")
private String cardHolder;
#ManyToOne(cascade = {CascadeType.MERGE, CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name = "UserId")
private User userJ;
#OneToMany(mappedBy = "cardJ")
private List<Purchase> purchases;
User.java
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="UserId")
private Integer userId;
#Column(name="FirstName")
private String firstName;
#Column(name="LastName")
private String lastName;
#Column(name="Email")
private String email;
#Column(name="Username")
private String username;
#Column(name="Password")
private String password;
#Column(name="RoleName")
private String roleName;
#OneToMany(mappedBy="userJ", cascade= CascadeType.ALL)
private List<Card> cards;
The error message is pretty clear. There is no field userId in your Card entity. Create one like that:
#Column(name = "UserId", insertable=false, updatable=false)
private Integer userId;
AFAIK, the problem seems to be that there's no userId column in the card table.

Hibernate modelmapper null value inserted

I'm starting to use Spring and Hibernate.
I have this Entity :
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false, unique = true)
private String username;
#NotEmpty
private String password;
#NotEmpty
private String firstname;
#NotEmpty
private String lastname;
#NotEmpty
private String email;
#ManyToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_role",
joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") })
private Set<Role> roles = new HashSet<>();
}
and this DTO :
public class UserDTO {
private String username;
private String password;
private String firstname;
private String lastname;
private String email;
private List<String> roles;
}
Role is like that (RoleType being an enum) :
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Enumerated(EnumType.STRING)
#Column(unique = true)
private RoleType name;
public Role() {}
public Role(RoleType name) {
this.name = name;
}
}
Now, in my controller, I want to create a new user :
public void createNewUser(UserDTO user){
ModelMapper _modelMapper=new ModelMapper();
User _newUser=_modelMapper.map(user, User.class);
//SECOND PART
Set<Role> _roles=new HashSet<>();
for (String _item : user.getRoles()) {
RoleType _roleType=RoleType.valueOf(_item);
Role _role=_roleRepository.findByName(_roleType);
_roles.add(_role);
}
_newUser.setRoles(_roles);
_userRepository.save(_newUser);
}
My concern is the second part (It does the trick but I'm not sure in term of good practices). I have 2 questions :
-is it the right way to fill the roles, being said that my UserDTO accepts a List<String> ?
-is it possible to map everything with the ModelMapper ? (I have tried but it fills my sql table only with the id, the name is null and it adds a line for each new user).
Thanks.

How to map 2 classes using model mapper, Entity to Dto

I want to convert two objects with same attributes using model mapper. How ever I cant because of many to many relationship.
private User fromEntity(UserEntity userEntity) {
LOGGER.info("Converting userEntity to user model with Id" +
userEntity.getUserId());
User user = modelMapper.map(userEntity,User.class);
LOGGER.info("Converted userEntity to user model with Id" +
userEntity.getUserId());
return user;
}
I have User and UserEntity classes. They are mapped with Role and RoleEntity classess:
Here is my User class:
public class User {
private Long userId;
private String userUsername;
private String userName;
private String userSurname;
private String password;
private String addres;
private String eMail;
private boolean active = false;
private String key;
//#JsonBackReference
private Set<Role> role ;
public User(){
role = new HashSet<>();
}
Role Class:
public class Role {
private Long roleId;
private String role;
private Set<User> user;
public Role(){
user = new HashSet<>();
}
//#JsonManagedReference
public Set<User> getUser() {
return user;
}
}
UserEntity Class:
#Entity
#Table( name="users" )
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userId")
private Long userId;
private String userUsername;
private String userName;
private String userSurname;
private String password;
private String addres;
private String eMail;
private boolean active;
private String key;
#JsonManagedReference
#ManyToMany( cascade = CascadeType.ALL, fetch = FetchType.EAGER )
#JoinTable(
name = "users_roles",
joinColumns = {#JoinColumn(name="userId")},
inverseJoinColumns = {#JoinColumn(name="roleId")}
)
private Set<RoleEntity> roleEntities;
public UserEntity(){
active=false;
roleEntities = new HashSet<>();
}
and RoleEntity class:
#Entity
#Table(name="roles")
public class RoleEntity {
#Id
#GeneratedValue
private Long roleId;
private String role;
#ManyToMany //( mappedBy = "roleEntities") //Bunu kaldırdım
private Set<UserEntity> userEntities ;
public RoleEntity(){
userEntities = new HashSet<>();
}
It gives me error when I login correctly:
ModelMapper mapping errors: 1) Converter org.modelmapper.internal.converter.CollectionConverter#735060fc failed to convert java.util.Set to java.util.Set. 1 error
I have changed my RoleEntity class attribute from:
#ManyToMany //( mappedBy = "roleEntities")
private Set<UserEntity> userEntities ;
to this:
#ManyToMany (mappedBy = "roleEntities", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<UserEntity> userEntities ;
That is how I resolved the problem.

Categories