I'm beginner in jpa and i encountered with composite query.
Then I started search solution. Many people advised use criteria API.
And so the question: how create similar query using criteriaQuery?
MySQL version
SELECT role FROM Role WHERE id_role=(SELECT id_role FROM Client WHERE email=:email)
Role
#Entity
#Table(name="role")
public class Role {
#Id
public int id_role;
private enum enumRole {ADMIN, CLIENT}
#Column(name="role")
private enumRole role;
public Role() {
}
public Role(enumRole role) {
this.role = role;
}
public String getRole() {
return this.role.name();
}
public void setRole(String role) {
this.role = enumRole.valueOf(role);
}
#OneToMany(targetEntity = Client.class)
private List clientList;
}
Client
#Entity
#Table(name ="client")
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long Id;
#Column(name="first_name", length = 25)
private String firstName;
#Column(name="surname", length = 25)
private String surName;
#Column(name="password", length = 30)
private String password;
#Column(name="email")
private String email;
#Column(name="username", length = 15)
private String username;
public Client() {
}
#ManyToMany(targetEntity = Ticket.class)
private Set ticketSet;
public Client(String firstName, String surName, String password, String email, String username) {
this.firstName = firstName;
this.surName = surName;
this.password = password;
this.email = email;
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurName() {
return surName;
}
public void setSurName(String surName) {
this.surName = surName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}
Can you not create a mapping between Client and Role? Either a #OneToMany or #ManyToMany? If so then you dont need to write any sql and could do this with a simple JPA Query method http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
Related
I am a beginner when it comes to API's and JSON serialization. I'm encountering a weird output. It seems that my JSON output is being wrongly formatted? I am using spring boot 1.59 and when I check my result in postman I am getting the following error:
controller
/**
*
* #return
*/
#PostMapping(value = "/getUser")
#ResponseBody
public User getUSer(#RequestParam int userID) {
System.out.println("Request Id is---->"+userID);
User user = userRepository.findById(userID);
return user;
}
User
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
//#GeneratedValue(strategy = GenerationType.IDENTITY)
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#NotNull
#Size(max = 65)
#Column(name = "first_name")
private String firstName;
#Size(max = 65)
#Column(name = "last_name")
private String lastName;
#NotNull
#Email
#Size(max = 100)
#Column(unique = true)
private String email;
#NotNull
#Size(max = 128)
private String password;
#OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "user")
private UserProfile userProfile;
// Hibernate requires a no-arg constructor
public User() {
}
public User(String firstName, String lastName, String email, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
// Getters and Setters (Omitted for brevity)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public UserProfile getUserProfile() {
return userProfile;
}
public void setUserProfile(UserProfile userProfile) {
this.userProfile = userProfile;
}
}
UserProfile
#Entity
#Table(name = "user_profiles")
public class UserProfile implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "phone_number")
#Size(max = 15)
private String phoneNumber;
#Enumerated(EnumType.STRING)
#Column(length = 10)
private Gender gender;
#Temporal(TemporalType.DATE)
#Column(name = "dob")
private Date dateOfBirth;
#Size(max = 100)
private String address1;
#Size(max = 100)
private String address2;
#Size(max = 100)
private String street;
#Size(max = 100)
private String city;
#Size(max = 100)
private String state;
#Size(max = 100)
private String country;
#Column(name = "zip_code")
#Size(max = 32)
private String zipCode;
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id", nullable = false)
private User user;
public UserProfile() {
}
public UserProfile(String phoneNumber, Gender gender, Date dateOfBirth,
String address1, String address2, String street, String city,
String state, String country, String zipCode) {
this.phoneNumber = phoneNumber;
this.gender = gender;
this.dateOfBirth = dateOfBirth;
this.address1 = address1;
this.address2 = address2;
this.street = street;
this.city = city;
this.state = state;
this.country = country;
this.zipCode = zipCode;
}
// Getters and Setters (Omitted for brevity)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserRepository
public interface UserRepository extends JpaRepository<User, Long> {
User findById(int id);
}
As well as a big long stack trace of fasterxml.jackson errors:
[jackson-databind-2.6.6.jar:2.6.6]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693) ~[jackson-databind-2.6.6.jar:2.6.6]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675) ~[jackson-databind-2.6.6.jar:2.6.6]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157) ~[jackson-databind-2.6.6.jar:2.6.6]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:149) ~[jackson-databind-2.6.6.jar:2.6.6]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:111) ~[jackson-databind-2.6.6.jar:2.6.6]
at
It happened due to infinite recursion between two entities and I solved using JsonManagedReference, JsonBackReference
a simple save in spring boot jpa / hibernate saves a row of nulls in the database.
package rest.api.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.sql.Blob;
import java.sql.Date;
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name="id")
private #JsonIgnore Long id;
#Column(name="created")
private Date created;
#Column(name="latitude")
private #JsonIgnore
Float latitude;
#Column(name="longitude")
private #JsonIgnore Float longitude;
#Column(name="password")
private #JsonIgnore String password;
#Column(name="user_name")
private #JsonIgnore String username;
#Column(name="pic_thumbnail")
private #JsonIgnore Blob picThumbnail;
#Column(name="first_name")
private #JsonIgnore String firstName;
#Column(name="middle_name")
private #JsonIgnore String middleName;
#Column(name="last_name")
private #JsonIgnore String lastName;
#Column(name="location_of_residence")
private #JsonIgnore String locationOfResidence;
#Column(name="telephone")
private #JsonIgnore String telephone;
#Column(name="email")
private #JsonIgnore String email;
#Column(name="description")
private #JsonIgnore String description;
#Column(name="date_of_birth")
private #JsonIgnore
java.sql.Date dob = null;
protected User () {}
public User(Long id, Date created, Float latitude, Float longitude, String password, String username, Blob picThumbnail, String firstName, String middleName, String lastName, String locationOfResidence, String telephone, String email, String description, Date dob) {
this.id = id;
this.created = created;
this.latitude = latitude;
this.longitude = longitude;
this.password = password;
this.username = username;
this.picThumbnail = picThumbnail;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.locationOfResidence = locationOfResidence;
this.telephone = telephone;
this.email = email;
this.description = description;
this.dob = dob;
}
// constructor for Logindetails
public User(Long id, String username, String password, String email) {
this.id = id;
this.created = null;
this.latitude = null;
this.longitude = null;
this.password = password;
this.username = username;
this.picThumbnail = null;
this.firstName = null;
this.middleName = null;
this.lastName = null;
this.locationOfResidence = null;
this.telephone = null;
this.email = email;
this.description = null;
this.dob = null;
}
public User(String username, String email, String password) {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Float getLatitude() {
return latitude;
}
public void setLatitude(Float latitude) {
this.latitude = latitude;
}
public Float getLongitude() {
return longitude;
}
public void setLongitude(Float longitude) {
this.longitude = longitude;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Blob getPicThumbnail() {
return picThumbnail;
}
public void setPicThumbnail(Blob picThumbnail) {
this.picThumbnail = picThumbnail;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLocationOfResidence() {
return locationOfResidence;
}
public void setLocationOfResidence(String locationOfResidence) {
this.locationOfResidence = locationOfResidence;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
}
#Repository
public interface UserRepository extends PagingAndSortingRepository {
}
package rest.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import rest.api.data.repository.UserRepository;
import rest.api.entity.User;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
#RestController
#Service
#Transactional
public class UserController {
private final UserRepository userDao;
#Autowired
public UserController(UserRepository userDao) {
this.userDao = userDao;
}
#Transactional
#RequestMapping(value = "/users/{user-id}", method = RequestMethod.GET)
public ResponseEntity<Resource<User>> getSpecificModel(#PathVariable(value = "user-id") Long userId) {
User specificUser = userDao.findOne(userId);
Resource<User> resource = new Resource<>(specificUser, linkTo(methodOn(MessageController.class)
.getSpecificModel(userId)).withSelfRel());
return ResponseEntity.ok(resource);
}
#Transactional
#RequestMapping(value = "/users/{user-id}", method = RequestMethod.DELETE)
public long remove(#PathVariable(value = "user-id") long userId) {
userDao.delete(userId);
return userId;
}
#RequestMapping(value = "/users", method = RequestMethod.POST)
public void registerLoginDetails(#RequestParam(name="username") String username,
#RequestParam(name="email") String email,
#RequestParam(name="password") String password) {
User loginDetails = new User(username, email, password);
userDao.save(loginDetails);
}
#Transactional
#RequestMapping(value = "/profile", method = RequestMethod.POST)
public void registerPersonalDetails() {
}
}
Every column in my users table can take a null, and so it is allowed to save a record in this state. I checked this by executing the equivalent query against the databse manually.
Does anyone have any ideas?
One glaring error is that the constructor in User used to register a user doesn't assign the username, email, password parameters passed in.
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "idUser")
public UserEntity getUserEntity() {
return teacher;
}
public void setUserEntity(UserEntity idTeacher) {
this.teacher = idTeacher;
}
The following code is in my data model. I use inheritance and I query this data the following way:
Query query1 = session.createQuery("FROM GroupEntity");
List<GroupEntity> groups = (List<GroupEntity>) query1.list();
The problem is. It will join now all the use information. But I only want to select a couple of things. For example. Only the username. And not the password.
Below the UserEnity:
#Entity
#Table(name = "User", schema = "", catalog = "")
#Inheritance(strategy = InheritanceType.JOINED)
public class UserEntity implements Serializable{
private int idUser;
private GroupEntity groupEntity;
private String email;
private String firstName;
private String lastName;
//ToDo Make this password secure!
private String password;
private boolean admin;
private boolean teacher;
public UserEntity(String email, String firstName, String lastName, String password, boolean admin, boolean teacher) {
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
this.password = password;
this.admin = admin;
this.teacher = teacher;
}
public UserEntity() {
}
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idUser")
public int getIdUser() {
return idUser;
}
public void setIdUser(int idUser) {
this.idUser = idUser;
}
#Basic
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Basic
#Column(name = "firstName")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Basic
#Column(name = "lastName")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Basic
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Basic
#Column(name = "admin")
public boolean getAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
#Basic
#Column(name = "teacher")
public boolean getTeacher() {
return teacher;
}
public void setTeacher(boolean teacher) {
this.teacher = teacher;
}
}
i have this error nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): app.Spring.domain.UserDetails.
I now have this user table and in profile i want to edit this UserDetails.
i was trying with GeneratedValue but this doing random id that not associate with user_id also checked generator but this method also dont work.There is so many options so i am lost now.Can someone show some method to mapp this two entities?
User
#Entity
#Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "user_id")
private Long user_id;
#NotBlank
#Size(min = 5, max = 20)
private String username;
#NotBlank
#Size(min = 8, max = 20)
private String password;
private String email;
private String name;
private String surname;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private UserDetails userDetail;
public User() {
}
public User(Long user_id, String username, String email, String name,
String surname, UserDetails userDetail, String password) {
super();
this.user_id = user_id;
this.username = username;
this.email = email;
this.name = name;
this.surname = surname;
this.userDetail = userDetail;
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Long getUser_id() {
return user_id;
}
public final void setUser_id(Long user_id) {
this.user_id = user_id;
}
public void setId(Long user_id) {
this.user_id = user_id;
}
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
User_Details
#Entity
#Table(name = "user_address")
public class UserDetails {
public UserDetails() {
super();
// TODO Auto-generated constructor stub
}
#Id
#Column(name = "user_id")
private Long id;
private String adres1;
private String adres2;
private String city;
private String postcode;
#OneToOne
#PrimaryKeyJoinColumn
private User user;
public UserDetails(Long id, String adres1, String adres2, String city,
String postcode, User user) {
super();
this.id = id;
this.adres1 = adres1;
this.adres2 = adres2;
this.city = city;
this.postcode = postcode;
this.user = user;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAdres1() {
return adres1;
}
public void setAdres1(String adres1) {
this.adres1 = adres1;
}
public String getAdres2() {
return adres2;
}
public void setAdres2(String adres2) {
this.adres2 = adres2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public void setId(Long id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
LOGIC
#RequestMapping(value = "/userDetails", method = RequestMethod.GET)
public String showForm(Model model,
#RequestParam(value = "id", defaultValue = "-1") Long id,
HttpSession session) {
app.Spring.domain.UserDetails va = (id > 0) ? reg.getAdress(id)
: new UserDetails();
model.addAttribute("detal", va);
return "userDetails";
}
#RequestMapping(value = "/userDetails", method = RequestMethod.POST)
public String submit(Model model, #ModelAttribute("detal") UserDetails va,
BindingResult result) {
validator.validate(va, result);
if (result.hasErrors()) {
return "userDetails";
}
reg.saveOrUpdateUserDetails(va);
return "profile";
}
I don't know how to do this with annotations but you might try to manually assign the (hopefully then already present) id fetched from user in the UserDetails entity in the #PrePresist annotated method.
User
#Entity
#Table(name = "USERS")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "user_id")
private Long user_id;
#NotBlank
#Size(min = 5, max = 20)
private String username;
#NotBlank
#Size(min = 8, max = 20)
private String password;
private String email;
private String name;
private String surname;
#OneToOne(mappedBy = "user")
private UserDetails userDetail;
User_detail
#Entity
#Table(name = "user_address")
public class UserDetails {
public UserDetails() {
super();
// TODO Auto-generated constructor stub
}
#Id
private Long id;
private String adres1;
private String adres2;
private String city;
private String postcode;
#OneToOne
#JoinColumn(name = "user_id")
private User user;
I have this code for login validation using a Struts2 action class which calls an EJB for LDAP validation and then if (LDAP credentials) validated, querying the user database to get the rest of the user information using the JPA entity bean which also acts like a POJO. Unlike the username, userid and other user info, password is not stored in the database, but for the sake of the POJO getter and setter method I attempt to include a dummy password field - for serving the Struts2 action form.
The problem is after ldap authentication, an exception occurs stating that the column "password" does not exist in the database (which was never meant to be anyway!)
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'PASSWORD' in 'field list'
Error Code: 1054
Call: SELECT PERSON_ID, ACTIVE_USER, EMAIL, FIRSTNAME, SURNAME, PASSWORD, FULLNAME, EMPLOYEE_NUMBER FROM xxte_employees WHERE (ACTIVE_USER = ?)
bind => [john.doe]
Query: ReadAllQuery(name="XxteEmployees.validateLogin" referenceClass=XxteEmployees sql="SELECT PERSON_ID, ACTIVE_USER, EMAIL, FIRSTNAME, SURNAME, PASSWORD, FULLNAME, EMPLOYEE_NUMBER FROM xxte_employees WHERE (ACTIVE_USER = ?)")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:687)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:530)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:529)
....
Here's the code from the entity bean:
public class XxteEmployees implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ACTIVE_USER")
private String activeUser;
#Column(name = "EMAIL")
private String email;
#Id
#Basic(optional = false)
#Column(name = "PERSON_ID")
private Double personId;
#Column(name = "EMPLOYEE_NUMBER")
private Double employeeNumber;
#Column(name = "FIRSTNAME")
private String firstname;
#Column(name = "SURNAME")
private String surname;
private String fullname;
private String password;
public XxteEmployees() {
}
public XxteEmployees(Double personId) {
this.personId = personId;
}
public String getActiveUser() {
return activeUser;
}
public void setActiveUser(String activeUser) {
this.activeUser = activeUser;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Double getPersonId() {
return personId;
}
public void setPersonId(Double personId) {
this.personId = personId;
}
public Double getEmployeeNumber() {
return employeeNumber;
}
public void setEmployeeNumber(Double employeeNumber) {
this.employeeNumber = employeeNumber;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
// BEGIN: objects not in db
public String getFullname() {
return firstname + ' ' + surname;
}
public void setFullname(String fullname) {
this.fullname = firstname + ' ' + surname;;
}
public String getPassword() {
return sifre;
}
public void setPassword(String password) {
this.password = password;
}
// END: objects not in db
Any workaround for this?
Annotate any fields that you don't want to be persisted as #Transient. It is in the javax.persistence package.