简体   繁体   中英

JPA, Spring web - how to “find” non-existent record in database

I have web written in Spring. I use Hibernate for JPA. I need to find entity in database, I get ID from user.

Problem is if ID is not in database - I get a NullPointerException.

Now I have:

People p;
try {
  p = peopleManager.findById(id);
  if (p != null) {
    model.addAttribute("message", "user exist, do any action");
  } else {
    model.addAttribute("message", "user NOT exist");
  }
} catch (NullPointerException e) {
  model.addAttribute("message", "user NOT exist");
}

but it looks terrible. How can I do it right?

There is complete example code:

package com.example.test.entity;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

public class People {  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private int id;

  @Column(name="name")
  private String name;

  @Column(name="age")
  private int age;
}
/* ---------------------------------------------------- */
package com.example.test.dao;

import java.util.List;
import com.example.test.entity.People;

public interface PeopleDao {  
    public void save(People people);  
    public void delete(People people);    
    public void update(People people); 
    public List<People> findAll();    
    public People findById(int id);
}
/* ---------------------------------------------------- */
package com.example.test.dao;

import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.test.entity.People;

@Repository
public class PeopleDaoImpl implements PeopleDao {

  @Autowired
  private SessionFactory sessionFactory;

  @Override
  public void save(People people) {
    this.sessionFactory.getCurrentSession().save(people);    
  }
  @Override
  public void delete(People people) {
    this.sessionFactory.getCurrentSession().delete(people);    
  }
  @Override
  public void update(People people) {
    this.sessionFactory.getCurrentSession().update(people);    
  }
  @Override
  public List<People> findAll() {
    return this.sessionFactory.getCurrentSession().createQuery("from People ORDER BY age").list();
  }
  @Override
  public People findById(int id) {
    return (People) this.sessionFactory.getCurrentSession().get(People.class, id);
  }
}
/* ---------------------------------------------------- */
package com.example.test.service;

import java.util.List;
import com.example.test.entity.People;

public interface PeopleManager {  
  public void save(People people);  
    public void delete(People people);    
    public void update(People people); 
    public List<People> findAll();    
    public People findById(int id);
}
/* ---------------------------------------------------- */
package com.example.test.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.test.dao.PeopleDao;
import com.example.test.entity.People;

@Service
@Transactional
public class PeopleManagerImpl implements PeopleManager {

  @Autowired
  private PeopleDao peopleDao;

  @Override
  public void save(People people) {
    peopleDao.save(people);  
  }
  @Override
  public void delete(People people) {
    peopleDao.delete(people);    
  }
  @Override
  public void update(People people) {
    peopleDao.update(people);
  }
  @Override
  public List<People> findAll() {
    return peopleDao.findAll();
  }
  @Override
  public People findById(int id) {
    return peopleDao.findById(id);
}
/* ---------------------------------------------------- */
package com.example.test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.test.entity.People;
import com.example.test.service.PeopleManager;

@Controller
public class PeopleController {  
  @Autowired
  private PeopleManager peopleManager;

  @RequestMapping(value = "/people/{id}", method = RequestMethod.GET)
  public String home(Model model, @PathVariable("id") String id) {    
    People p;
    try {
      p = peopleManager.findById(Integer.parseInt(id));
      if (p != null) {
        model.addAttribute("message", "user exist, do any action");
      } else {
        model.addAttribute("message", "user NOT exist");
      }
    } catch (NullPointerException e) {
      model.addAttribute("message", "user NOT exist");
    }
    return "people";
  }  
}
/* ---------------------------------------------------- */

Refactor the null check out of your controller. Controllers shouldn't have any business logic in them. The correct place for this is inside your service class.

@Override
@Transactional
public People findById(int id) throws ObjectNotFoundException{
    People people = null;        
    people  = peopleDao.findById(id);
    if(people == null){
        throw new ObjectNotFoundException("Couldn't find a People object with id " + id);
    }
    return people;
}

I would write a custom exception that extends RuntimeException that is thrown if your People object is null.

This is best practice as you can reuse your ObjectNotFoundException in all your service layers. Then make all your controller methods throw Exception and investigate global error handling for controllers.

Also, it is best practice to not annotate your entire service class as @Transactional , mark the individual methods. That way if you need to add additional methods to your services you can choose if you want them to run in a transactional context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM