In doing a project using Spring MVC. The basic is: when a student signs up, his data will be stored in the database table and the password will be sent to the students mail address.
So I have:
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String dosignup(#Valid #ModelAttribute("student") Student student, HttpServletRequest request,
HttpServletResponse response, BindingResult result) {
studentService.addNewStudent(student.getName(),
student.getUsername(), student.getEmail(), student.getPassword());
studentService.sendEmail(student);
}
StudentDao interface is:
public interface StudentDao {
public void saveStudent(Student student);
public void fetchinfo(Student student);
}
fetchinfo implementation in StudentDaoImpl is:
public void fetchinfo(Student student) {
String hql = "select password from student where email = :email";
sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("email", student.getEmail()).uniqueResult();
}
StudentService interface is:
public interface StudentService {
Student addNewStudent(String name, String username, String email, String password);
void sendEmail(Student student);
Student fetchinfo(String email);
}
and StudentServiceImpl is:
public User fetchinfo(String email) {
Student student = new Student(email);
studentDao.fetchinfo(student);
return student;
}
public void sendEmail(Student student) {
mailService.accountActivation(student);
}
Now, the problem is: a mail is sent to the students mail address, but the password is null. Can someone explain why this happens?
In StudentDaoImpl you are not setting the password property from the db query result. Rewrite relevant line as:
student.setPassword(sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("email", student.getEmail()).uniqueResult());
Update
While we are in Hibernate, by convention Student entity should have getters and setters for each property. Then I would rewrite StudentDaoImpl as:
public void fetchinfo(String email) {
String hql = "select s from student s where s.email = :email";
return (Student)sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("email", email).uniqueResult();
}
..and call it with student = studentDao.fetchinfo(email); (of course naming of methods should change).
Related
I have 2 classes: Employee and DailyReport and I call both in another class like this:
public class Bean {
private Employee employees;
private DailyReport dailyReports;
//getters and setters
and the controller for edit is:
#RequestMapping(value = "/editEmployee", method = RequestMethod.GET)
public String getEdit(#RequestParam(value="emp_id") Integer emp_id, Model model) {
Bean bean=new Bean();
bean.setEmployees(employeeService.getEmployee(emp_id));
model.addAttribute("bean",bean);
return "addemployee";
}
#RequestMapping(value = "/editEmployee", method = RequestMethod.POST)
public String postEdit(#RequestParam(value="emp_id") Integer emp_id, #ModelAttribute("bean")Bean bean) {
Employee employee=new Employee();
employee.setEmp_id(emp_id)//how can I set the emp_id??
employeeService.edit(employee);
return "search";
}
My question is: In post method how can I set the employee id for editing?
#Umesh Sanwal : this is my dao class:
public void edit(Employee employee) {
Session sessions = session.getCurrentSession();
Employee existingEmployee = (Employee) sessions.get(Employee.class,
employee.getEmp_id());
existingEmployee.setEmp_id(employee.getEmp_id());
existingEmployee.setName(employee.getName());
existingEmployee.setDesignation(employee.getDesignation());
existingEmployee.setLocation(employee.getLocation());
existingEmployee.setEmployee_type(employee.getEmployee_type());
sessions.save(existingEmployee);
}
and service class is:
#Transactional
public void edit(Employee employee) {
employeeDao.edit(employee);
and the bean class is:
public class Bean {
private Employee employees;
private DailyReport dailyReports;
my question is how can i set the edit operation in controller??
#PutMapping(path = "{studentId}")
public void updateStudent(
#PathVariable("studentId") Long studentId,
#RequestParam(required = false) String name,
#RequestParam(required = false) String email){
studentService.updateStudent(studentId, name, email);
}
#Transactional
public void updateStudent(Long studentId, String name, String email){
Student student = studentRepository.findById(studentId)
.orElseThrow(() -> new IllegalStateException("Student with " +studentId+" does not exist" ));
student.setName(name);
student.setEmail(email);
}
}
The problem is when I do PUT method in POSTMAN it gives no error but values in "name" and "email" are NULL. How can I fix it?
Here is my POSTMAN request.
https://i.stack.imgur.com/KHYVW.png
Your api expects optional request params and you are giving request body in postman. The above api will work for /student/1?name=John&email=example#abc.com
If you want to use request body to work with this api i.e., form data submit them change the api to use request body which will be (#RequestBody Student studentData) where Student is a class having 2 string variables name & email. You can create a new class StudentRequest having only request attributes for your put/post apis or you can reuse Student class.
#PutMapping(path = "{studentId}")
public void updateStudent(
#PathVariable("studentId") Long studentId,
#RequestBody(required = true) Student student){
studentService.updateStudent(studentId, student);
}
#Transactional
public void updateStudent(Long studentId, Student studentData){
Student student = studentRepository.findById(studentId)
.orElseThrow(() -> new IllegalStateException("Student with " +studentId+" does not exist" ));
student.setName(studentData.getName());
student.setEmail(studentData.getEmail());
studentRepository.save(student);
}
Repository Class:
#Repository // This my architecture repository class.
public class UserRepositoryImp implements UserRepository {
private EntityManager entityManager;
#Autowired
public UserRepositoryImp(EntityManager entityManager) {
this.entityManager = entityManager;
}
private static final String MY_SQL_COUNT_EMAIL =
"SELECT count(e) FROM User e WHERE e.email=:email "; // This is hibernate query.
#Override
public Integer getCountByEmail(String email) {
Session session = entityManager.unwrap(Session.class);
TypedQuery<Integer> query = session.createQuery(MY_SQL_COUNT_EMAIL, null);
query.setParameter("email", email); // This is return count in database check database
// .. if you email this database passing already exist this email but your count zero created new email.
return query.executeUpdate();
}
}
Service Class:
#Service
#Transactional
public class UserServiceImp implements UserService {
#Autowired
UserRepository userRepository;
#Override
public User validateUser(String email, String password) throws EtAuthException {
return null;
}
#Override
public User registerUser(User user) throws EtAuthException {
Pattern pattern = Pattern.compile("^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2, 6} $ "); // This regex.
if (pattern.matcher(user.getEmail()).matches()) {
throw new EtAuthException("Invalid email format"); // This is check email regex.
}
Integer count = userRepository.getCountByEmail(user.getEmail()); // This is my method
// .. count email in database and repository methods
if (count > 0) {
throw new EtAuthException("Email already in use");
}
Integer userId = userRepository.create(user);
return userRepository.findById(userId);
}
}
Postman Error:
Cannot invoke "java.lang.Class.isAssignableFrom(java.lang.Class)"
because "resultClass" is null"
Problem:
My problem is actually. I want to write a query to hibernated but for some reason it doesn't work. For such operations in spring boot, ie typing a query, for example polling email, put delete add and updated, how do I do it? I need to query me. I can't solve this problem.
You are calling executeUpdate() for a select query. Try using getSingleResult() instead.
#Override
public long getCountByEmail(String email) {
Session session = entityManager.unwrap(Session.class);
String query = "SELECT count(e) FROM User e WHERE e.email = :email";
TypedQuery<Long> typedQuery = session.createQuery(query, Long.class);
typedQuery.setParameter("email", email);
return typedQuery.getSingleResult();
}
OR
#Override
public long getCountByEmail(String email) {
String query = "SELECT count(e) FROM User e WHERE e.email = :email";
TypedQuery<Long> typedQuery = entityManager.createQuery(query, Long.class);
typedQuery.setParameter("email", email);
return typedQuery.getSingleResult();
}
I have the following code:
public interface UserRepository extends CrudRepository<User, Integer> {
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (?,?,?)", nativeQuery = true)
void insertUserToUsers(String email, String password, String name);
}
I don't want to pass the values, i want to pass a user object like this:
void insertUserToUsers(User user);
Try this
public interface UserRepository extends CrudRepository<User, Integer> {
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (:#{#user.email},:#{#user.firstname},:#{#user.name})", nativeQuery = true)
void insertUserToUsers(#Param("user") User user);
}
Try this code,
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (?,?,?)", nativeQuery = true)
void insertUserToUsers(String email, String password, String name);
default void insertUserToUsers(User user) {
return insertUserToUsers(user.getEmail(), user.getPassword(), user.getName());
}
Where you use your UserRepository you can use the default method to save user:
ex:
#Service
public class MyService{
#Autowired
private UserRepository userRepository ;
public void example(User user){
userRepository.save(user)
}
}
Because CrudRepository give us some default methods , you can check here
I used following method to get predefined object .
public Patient getUserNameAndPassword(String username, Session session) {
Patient patient=(Patient)session.get(Patient.class,username);
return patient;
}
After execute this method , following exception was generated .
org.hibernate.TypeMismatchException: Provided id of the wrong type for class beans.Patient. Expected: class java.lang.Integer, got class java.lang.String
PatientService.java
public class PatientService {
private static PatientDAOInterface patientDAOInterface;
public PatientService() {
patientDAOInterface = new PatientDAOImpl();
}
public Session getSession() {
Session session = patientDAOInterface.openCurrentSession();
return session;
}
public Transaction getTransaction(Session session) {
return patientDAOInterface.openTransaction(session);
}
public Patient getUserNameAndPassword(String username){
Session session = patientDAOInterface.openCurrentSession();
Transaction transaction = null;
Patient patient=new Patient();
try{
transaction = patientDAOInterface.openTransaction(session);
patient=patientDAOInterface.getUserNameAndPassword(username, session);
transaction.commit();
}catch(Exception ex){
ex.printStackTrace();
}finally{
session.close();
}
return patient;
}
}
PatientDAOInterface .java
public interface PatientDAOInterface
{
public Patient getUserNameAndPassword(String username,Session session);
public Session openCurrentSession();
public Transaction openTransaction(Session session);
}
PatientDAOImpl.java
public class PatientDAOImpl implements PatientDAOInterface {
#Override
public Patient getUserNameAndPassword(String username, Session session) {
Patient patient=(Patient)session.get(Patient.class,username);
return patient;
}
private static final SessionFactoryBuilder sessionFactoryBuilder = SessionFactoryBuilder.getInstance();
#Override
public Session openCurrentSession() {
Session currentSession = sessionFactoryBuilder.getSessionFactory().openSession();
return currentSession;
}
#Override
public Transaction openTransaction(Session session) {
Transaction beginTransaction = session.beginTransaction();
return beginTransaction;
}
}
I have mentioned my works above.
Actually , I want to pass a String through parameters and get a Patient object.
I am familiar with passing an Integer instead of a String. But I have no idea about this .
Have any ideas ?
You want to find a Patient by his username? Because here you are trying to find him by his ID and you are passing a String representing username. You should write your own query/criteria for getting a Patient by username. Something like this:
Criteria criteria = session.createCriteria(Patient.class);
criteria.add(Restrictions.eq("username", username);
List<Patient> patients = criteria.list();
Or query version:
String hql = "FROM Patient p WHERE p.username = "+username;
Query query = session.createQuery(hql);
List patients = query.list();
I found a answer to the problem.
public Patient getUserNameAndPassword(String username, Session session) {
Query query=session.createQuery("from Patient where user_name= :username");
query.setParameter("username", username);
List list = query.list();
Patient patient=(Patient) list.get(0);
return patient;
}
This is worked for me .
Thanks.