get dbref from document in Mongo using Java - java

I cannot get dbRef object from Mongo. In my entity package I have a User class with a Parent class inheriting.
Here is the User class:
public class User {
#Id
private ObjectId id;
#DBRef
private Account account;
private String name;
public String getId() {
if (id != null) {
return id.toStringMongod();
}
return null;//no id
}
public void setId(ObjectId objectId) {
this.id = objectId;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
}
As you can see above, I am putting an object of Account here.
My Parent class simply extends User:
#Document
public class Parent extends User {
#JsonProperty("is_activated")
private boolean isActivated;
public boolean isActivated() {
return isActivated;
}
public void setActivated(boolean isActivated) {
this.isActivated = isActivated;
}
}
Note: nothing magic with isActivated.
In my ParentDaoImpl class:
#Service
public class ParentDaoImpl extends AbstractDaoImpl implements ParentDao {
#Override
public Parent getParentByLogin(String login) {
Query query = new Query(Criteria.where("login").is(login));
return mongoOperations.findOne(query, Parent.class, "parents");
}
}
The problem is that if I call getParentByLogin method, it returns evertyning but Account field is null. Maybe findOne doesn't give dbRef inside. I think in relational Databases, there would be something like join. I want my method to give me account field as well.
Thanks for your help!

Can you try something like this.
....
#Field("fieldName")
#DBRef(collection = "mongoCollectionName")
private Account account;
....

Related

Cannot invoke "UserRepository.findAll()" because "userRepository" is null

I want to create a login method for my spring application. But when I try to call the
getUserByAuthentication
method, I get a null pointer exception. Here is my code:
Function calling the error:
#PostMapping(path = "/online")
public ResponseEntity<?> onlineRequest(#RequestBody OnlineRequest onlineRequest) {
User user = null;
UserManager userManager = new UserManager();
user = userManager.getUserByAuthentication(onlineRequest.getUsername(), onlineRequest.getPassword());
if (user!=null){
user.setLatestTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>("You are now online, Enjoy!", HttpStatus.OK);
} else {
return new ResponseEntity<>("Invalid login", HttpStatus.valueOf(403));
}
}
Get User by Authentication class:
public class UserManager {
#Autowired
private UserRepository userRepository;
public User getUserByID(int id){
return userRepository.findById(id).get();
}
public User getUserByAuthentication(String name, String password){
Iterable<User> userList = userRepository.findAll();
ArrayList<User> users = new ArrayList<>();
userList.forEach(users::add);
User user = null;
for (User u : users){
if (u.getUsername().equals(name) && u.getPassword().equals(password)){
user = u;
}
}
return user;
}
}
Repository:
#Repository
public interface UserRepository extends CrudRepository<User, Integer> {
}
User class:
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
//Initialize
private String username;
private String password;
private boolean hasAccess;
ArrayList<Integer> inChannels;
long latestTimeStamp;
public long getLatestTimeStamp() {
return latestTimeStamp;
}
public void setLatestTimeStamp(long latestTimeStamp) {
this.latestTimeStamp = latestTimeStamp;
}
public ArrayList<Integer> getInChannels() {
return inChannels;
}
public void setInChannels(ArrayList<Integer> inChannels) {
this.inChannels = inChannels;
}
public Long getId() {
return id;
}
public User() {
}
public boolean hasAccess() {
return hasAccess;
}
public void setAccess(boolean hasAccess) {
this.hasAccess = hasAccess;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
You can't use #Autowired without one of the annotation that define a component in spring, so in your case, you can use #Service on UserManager like this:
#Service
public class UserManager {
and also don't use static on your method, you have to inject the UserManager component in the controller, as you do with your repository:
#Autowired
private UserManager userManager;
Then you can use:
user = userManager.getUserByAuthentication(onlineRequest.getUsername(), onlineRequest.getPassword());
^^^^^^^^^^^
I fixed it by adding the find function into the repository interface.

How to optimize two classes that have similar/repeated code with different method signature/return type?

I have the following interface
public interface IEntity {
String getId();
void setId(String id);
String getStatus();
void setStatus(String status);
}
Two clasess i.e. AuthEntity and UserEntity that implements the above interface
public class AuthEntity implements IEntity {
private String id;
private String status;
public String getId() {return id;}
public void setId(String id) {this.id = id;}
public String getStatus() {return status;}
public void setStatus(String status) {this.status = status;}
}
public class UserEntity implements IEntity {
private String id;
private String status;
public String getId() {return id;}
public void setId(String id) {this.id = id;}
public String getStatus() {return status;}
public void setStatus(String status) {this.status = status;}
}
I have 2 mapper classes as follows,
#Component("userMapper")
public class UserMapper {
public UserEntity map(String id, String status, UserEntity userEntity) {
userEntity.setId(id);
userEntity.setStatus(status);
return userEntity;
}
}
#Component("authMapper")
public class AuthMapper {
public AuthEntity map(String id, String status, AuthEntity authEntity) {
authEntity.setId(id);
authEntity.setStatus(status);
return authEntity;
}
}
And lastly, there's Handler class where i'm saving the entities i.e. User and Auth in their corresponding databases based on condition checking as follows:
public class Handler {
#Autowired
private UserMapper userMapper;
#Autowired
private AuthMapper authMapper;
private boolean flag = true;
//some code
public void saveResponse() {
IEntity entity = null;
String id = "1234";
if(flag) {
//getting user entity using AuthHandler(code not included here) from Auth table in mongo-db
entity = AuthHandler.getEntity(id);
} else {
//getting user entity using UserHandler(code not included here) from User table in mysql-db
entity = UserHandler.findByUserId(id);
}
if(entity != null) {
//some code
if(flag) {
authMapper.map(id,status,(AuthEntity)entity);
AuthHandler.save((AuthEntity)entity); //calling AuthHandler to save entity in Auth mongo-db
} else {
userMapper.map(id,status,(UerEntity)entity);
UserHandler.update((UserEntity)entity); //calling UserHandler to save entity in User mysql-db
}
//some code
}
}
//some code
}
So, my question is that, is there a way I can generalize/optimize the above 2 mapper classes into one i.e. instead of 2 mapper classes can I have only one mapper class and make calls based on the entity class (User or Auth). For example, can I try/have something like this,
#Component("mapper")
public class Mapper {
public IEntity map(String id, String status, IEntity entity) {
entity.setId(id);
entity.setStatus(status);
return entity;
}
}
and in above Handler class method, can I try something like this without typecasting entity in above authMapper.map(...) or userMapper.map(...),
if(entity != null) {
//some code
if(flag) {
entity = AuthHandler.getEntity(id);
} else {
entity = UserHandler.findByUserId(id);
}
mapper.map(id,status,entity);
if(flag) {
AuthHandler.save((AuthEntity)entity); //calling AuthHandler to save entity in Auth mongo-db
} else {
UserHandler.update((UserEntity)entity); //calling UserHandler to save entity in User mysql-db
}
//some code
}
Any help would be appreciated. Thanks!!

How to insert a json body with multiple data to multiple tables with relationship in springboot

I have two entities: UserEntity and LoginEntity and crudrepositories for each. The entities have a relationship of OneToOne where one user will have one login account. I also created a controller and I can get all the data from the database i.e when call getalluser I get all users with their relationship to login. and when I call getAllLogins I get all logins accounts. I also managed to insert the user and the login using API each individually and it's working fine but this will omit the foreign-key user_id.
Now since am knew am stack on how to insert the user and login each respectively with their relationships through one json body
#Entity#Table(name="user_table")public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long uid;
private String fname;
private String lname;
#OneToOne( cascade = CascadeType.ALL, mappedBy = "userEntityFk")
private LoginEntity logins;
public UserEntity() {
super();
}
public Long getUid() {
return uid;
}
public void setUid(Long uid) {
this.uid = uid;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public LoginEntity getLogins() {
return logins;
}
public void setLogins(LoginEntity logins) {
this.logins = logins;
}
public UserEntity(Long uid, String fname, String lname, LoginEntity logins) {
super();
this.uid = uid;
this.fname = fname;
this.lname = lname;
this.logins = logins;
}
#Entity #Table(name="login_table") public class LoginEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long lid;
private String username;
private String password;
#OneToOne(cascade = CascadeType.ALL )
private UserEntity userEntityFk;
public LoginEntity() {
super();
}
public LoginEntity(Long lid, String username, String password, UserEntity userEntityFk) {
super();
this.lid = lid;
this.username = username;
this.password = password;
this.userEntityFk = userEntityFk;
}
public Long getLid() {
return lid;
}
public void setLid(Long lid) {
this.lid = lid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public UserEntity getUserEntityFk() {
return userEntityFk;
}
public void setUserEntityFk(UserEntity userEntityFk) {
this.userEntityFk = userEntityFk;
}
}
#Repository
public interface LoginRepo extends CrudRepository<LoginEntity, Integer> {
}
#Repository
public interface UserRepo extends CrudRepository<UserEntity, Integer> {
}
#RestController
#RequestMapping(path="/api")
public class MainController {
#Autowired
private UserRepo userRepository;
#Autowired
private LoginRepo loginRepository;
//===this works fine i can get all the users after insert
#GetMapping(path="/user_acc")
public #ResponseBody Iterable<UserEntity> getAllUsers() {
// This returns a JSON or XML with the users
return userRepository.findAll();
}
//================this too works fine after insert
#GetMapping(path="/login_acc")
public #ResponseBody Iterable<LoginEntity> getAlllogins() {
// This returns a JSON or XML with the users
return loginRepository.findAll();
}
//===adding single user works fine. and it returns user_id
#PostMapping("/user_acc")
public Long addNewUser(#RequestBody UserEntity userz){
UserEntity ue = userRepository.save(userz);
return ue.getUid();
}
//===this works but the foreign key not inserted and thats where my problem is
#PostMapping("/login_acc")
public LoginEntity addNewLogin(#RequestBody LoginEntity loginz){
return loginRepository.save(loginz);
}
}
class UserLogin{
UserEntity myuser;
LoginEntity mylogin;
public UserEntity getMyuser() {
return myuser;
}
public void setMyuser(UserEntity myuser) {
this.myuser = myuser;
}
public LoginEntity getMylogin() {
return mylogin;
}
public void setMylogin(LoginEntity mylogin) {
this.mylogin = mylogin;
}
}
result on post http://localhost:8080/api/login_acc. account created but no foreign key
result on post http://localhost:8080/api/login_acc. account created but no foreign key
{
"lid": 1,
"username": "admin1",
"password": "11111",
"userEntityFk": null
}
result on geting all users on get method http://localhost:8080/api/user_acc
{
"uid": 1,
"fname": "hassan",
"lname": "zahor",
"logins": null
}
what i want to post is this body below to multiple tables
{
"fname":"hassan",
"lname":"zahor",
"username": "admin5",
"password": "55555"
}
This one should works better :
{
"fname":"hassan",
"lname":"zahor",
"userEntityFk" : {
"username": "admin5",
"password": "55555"
}
}
However, you will get an error if your endpoint returns an object that contains a loop inclusion : spring will try to map it into json indefinitely.
You can correct this issue to map your result into another object before returning it from your controller, or just remove the property "logins" from UserEntity.

Getting null when trying to get an auto-generated id from entity which is got by findByVariable method using JPARepository

I have this model:
User.java
#Entity
#Table(name = "`user`")
public class User {
private Long id;
private String username;
private String phone;
#Override
public int hashCode() {
return new Long(id).hashCode();
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof User)) {
return false;
}
return this.id == ((User) obj).getId();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
(...other getters and setters...)
}
This piece of code in my controller:
UserController.java
(...)
#RequestMapping(value = "/user/updatePhone", method = RequestMethod.GET)
public String updatePhone(Model model) {
model.addAttribute("userForm", userService.findByUsername("testUsername"));
return "user/updatePhone";
}
#RequestMapping(value = "/user/updatePhone", method = RequestMethod.POST)
public String updatePhone(#ModelAttribute("userForm") User userForm, BindingResult bindingResult, Model model) {
userService.updatePhone(userForm);
return "redirect:/user/view";
}
(...)
And this in my service:
UserServiceImpl.java
#Service
#Transactional
public class UserServiceImpl implements UserService {
(...)
#Override
public void updatePhone(User user) {
User entity = userRepository.findById(user.getId());
if (entity != null) {
entity.setPhone(user.getPhone());
}
}
(...)
}
My problem is that when I try to get the id from the user object in the UserServiceImpl class, I am getting a null. Do you know what I must do in order to get the id properly setted in my user object? Probably it's a problem with the method findByUsername(...) of the userRepository class which returns the object without the id (which is prelude by #Id and #GeneratedValue(...) annotations in my model).

Eclipse 'generate entities from tables' and 'many to one' relation

i am developing a simple Java EE application, that uses database. It has two tables (Admin and Session signature) connected with many to one relation.
When i used eclipse to generate entities from tables, my attribute that links both tables was generated like this:
//bi-directional many-to-one association to Admin
#ManyToOne
#JoinColumn(name="owner")
private Admin admin;
Problem is, my owner attribute is Integer in database, and it has been created as Admin type.
Now when i want to pass some Integer variable to input it to database i get error:
The method setAdmin(Admin) in the type Signaturesession is not applicable for arguments (int).
Or when i want to cast it to (Admin) like this (taking it from session):
(Admin)session.getAttribute("adminId")
I get Jboss Error:
javax.servlet.ServletException: java.lang.ClassCastException: java.lang.Integer cannot be cast to com.podpisy.entities.Admin
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
secure.SecurityCheckFilter.doFilter(SecurityCheckFilter.java:100)
I am sure that this can be done easy, but i'm just really bad using Java.
Thanks for any help.
EDIT:
My Admin.java class:
package com.podpisy.entities;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name="admins")
#NamedQuery(name="Admin.findAll", query="SELECT a FROM Admin a")
public class Admin implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private String login;
private String password;
//bi-directional many-to-one association to Signature
#OneToMany(mappedBy="admin")
private List<Signature> signatures;
//bi-directional many-to-one association to Signaturesession
#OneToMany(mappedBy="admin")
private List<Signaturesession> signaturesessions;
public Admin() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getLogin() {
return this.login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Signature> getSignatures() {
return this.signatures;
}
public void setSignatures(List<Signature> signatures) {
this.signatures = signatures;
}
public Signature addSignature(Signature signature) {
getSignatures().add(signature);
signature.setAdmin(this);
return signature;
}
public Signature removeSignature(Signature signature) {
getSignatures().remove(signature);
signature.setAdmin(null);
return signature;
}
public List<Signaturesession> getSignaturesessions() {
return this.signaturesessions;
}
public void setSignaturesessions(List<Signaturesession> signaturesessions) {
this.signaturesessions = signaturesessions;
}
public Signaturesession addSignaturesession(Signaturesession signaturesession) {
getSignaturesessions().add(signaturesession);
signaturesession.setAdmin(this);
return signaturesession;
}
public Signaturesession removeSignaturesession(Signaturesession signaturesession) {
getSignaturesessions().remove(signaturesession);
signaturesession.setAdmin(null);
return signaturesession;
}
}
My Signaturesession.class:
package com.podpisy.entities;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the signaturesession database table.
*
*/
#Entity
#NamedQuery(name="Signaturesession.findAll", query="SELECT s FROM Signaturesession s")
public class Signaturesession implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private String device;
private String name;
private int signatures;
private int time;
private String type;
private int users;
//bi-directional many-to-one association to Admin
#ManyToOne
#JoinColumn(name="owner")
private Admin admin;
public Signaturesession() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getDevice() {
return this.device;
}
public void setDevice(String device) {
this.device = device;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getSignatures() {
return this.signatures;
}
public void setSignatures(int signatures) {
this.signatures = signatures;
}
public int getTime() {
return this.time;
}
public void setTime(int time) {
this.time = time;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public int getUsers() {
return this.users;
}
public void setUsers(int users) {
this.users = users;
}
public Admin getAdmin() {
return this.admin;
}
public void setAdmin(Admin admin) {
this.admin = admin;
}
}
You should pass an Admin object which surely has an int id field.
So you've to make something like this
Admin myAdmin=new Admin(id,.. other properties);
mySignaturesession.setAdmin(myAdmin);
EDIT
Above is valid if you want to associate and Admin to your SignatureSession object. Instead if you have an Admin ojbect in Session you just have to execute
Admin anAdmin=(Admin)session.getAttibute("adminId");
Admin myAdmin=new Admin(id,.. other properties);
or
Admin myAdmin=new Admin();
myAdmin.setId(anId);
But, i repeat, it depends from what you have in the Session and which objects you handle.
And, as you look to be using JPA, dont forget to do something like em.persist or em.merge on your objects.
Maybe you should get a little deeper on how JPA works.

Categories