Как исправить исключение нулевого указателя после применения триггера в базе данных под аннотацией @Transactional? - PullRequest
1 голос
/ 03 июня 2019

Я работаю над проектом начальной загрузки с модулем Hibernate ORM, использующим MySQL в качестве базы данных.

Существует база данных college_students, которая содержит таблицу student, и эта таблица содержит следующие поля:

  CREATE TABLE student(

    _id INTEGER(11) NOT NULL, 
    student_name VARCHAR(50) NOT NULL,
    attend_lecture INTEGER(11) NOT NULL,
    iso_dom INTEGER(11) NOT NULL,
    iso_dow INTEGER(11) NOT NULL,
    iso_month INTEGER(11) NOT NULL,
    iso_year INTEGER(11) NOT NULL,
    iso_week INTEGER(11) NOT NULL,
    updated_on BIGINT(20) NOT NULL, 
    PRIMARY KEY (_id, updated_on)
 );

В этом проекте есть ученический класс.Ученический класс - это класс модели в моем проекте

  @Entity
  @Table(name="student")
  @NamedQuery(name="Student.findAll", query="SELECT s FROM Student s")
  public class Student implements Serializable {
  private static final long serialVersionUID = 1L;

  @EmbeddedId
  private StudentPK id;

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

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

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

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

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

  @Column(name="updated_on")
  private String updatedOn;
}

Ученический класс StudentPK - это

 @Embeddable
 public class StudentPK implements Serializable {
      //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(name="_id")
    private int Id;

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

    public StudentPK() {
    }
    public StudentPK(int Id, String updatedOn) {
        super();
        this.Id = Id;
        this.updatedOn = updatedOn;
    }
    public int getId() {
       return this.Id;
    }
    public void setId(int Id) {
       this.Id = Id;
    }
    public String getUpdatedOn() {
       return this.updatedOn;
    }
    public void setUpdatedOn(String updatedOn) {
        this.updatedOn = updatedOn;
    }

    public boolean equals(Object other) {
       if (this == other) {
            return true;
       }
       if (!(other instanceof StudentPK)) {
            return false;
       }
       StudentPK castOther = (StudentPK)other;
       return 
           (this.Id == castOther.Id)
           && this.updatedOn.equals(castOther.updatedOn);
   }

   public int hashCode() {
        final int prime = 31;
        int hash = 17;
        hash = hash * prime + this.Id;
        hash = hash * prime + this.updatedOn.hashCode();

        return hash;
   }
 }

Ученический класс StudentService запрашивает обращение к базе данных Mysql с помощью StudentRepository, которая расширяется с помощью CrudRepository

   @Service
   @Transactional(propagation = Propagation.REQUIRES_NEW)
   public class StudentService {

      private static final Logger logger =LoggerFactory.getLogger(StudentService.class);

      @Autowired
      StudentRepository studentRepository;

      @PersistenceContext
      private EntityManager entityManager;

      public Student insertIntoStudentTable(String name, int attendLecture, int isoDom, int isoDow, int isMonth) {

      // insert into Student table
      BigInteger currentTime = BigInteger.valueOf(new Date().getTime());
      Student student = new Student();
      student = StudentMapper.registerStudent(student, name,
              new StudentPK(Constants.INSERT_ID_DEFAULT_VALUE, currentTime.toString()), attendLecture, 
          Constants.INSERT_RECORD_TYPE_DEFAULT_VALUE, isoDom, isoDow, isMonth);                  
      student = studentRepository.save(student);
      logger.debug("detach stduent");
      String updatedOn = student.getId().getUpdatedOn();
      logger.debug("updated on : " + updatedOn);
      entityManager.detach(student);
      student = studentRepository.findByUpdatedOnAndNewRecordType(updatedOn); 
      logger.debug("after detach and query");
      logger.debug("student id : " + student.getId());   //  getting error at this point null pointer error 
      return student;
     }
  }

NOTE:

Для таблицы учеников применяется триггер, который увеличивает значение Student.id в таблице.Например:

        _id | student_name | attend_lecture |iso_dom | iso_dow | iso_month| iso_year | iso_week  | updated_on   
        1   |   Rahul        |  15             |  2       |   1  | 1 |  2019   |  1   |    2588899955

Таким образом, таблица ученика, имеющая 1 запись и значение поля _id, назначается триггером.

Trigger

     delimiter |
     CREATE TRIGGER Student_bit BEFORE INSERT ON Student
 FOR EACH ROW
 BEGIN
 SET @_id = NULL;
 IF NEW._id = 0 THEN
 SELECT COALESCE(MAX(_id) + 1, 1) INTO @_id FROM student;
 SET NEW._id = @_id;
 END IF;
 END;
     |
     delimiter ;

Здесь исходный кодработает отлично.Изменение триггера: значение поля _id от 0 до 1 или какое (максимальное число + 1)

Но после применения триггера в объекте класса Student не сохраняется никаких данных для этой проблемы. Мне нужно применить запрос, чтобы получить данные избазы данных.

Становится хуже, когда я применил аннотацию @Transactional к классу StudentService.java.

Error:

           2019-05-31 18:15:08.899 DEBUG 6972 --- [nio-8080-exec-4] com.test.student.service.Test2Service   : after detach and query
           2019-05-31 18:15:08.906 ERROR 6972 --- [nio-8080-exec-4] c.t.s.r.GlobalExceptionHandler           : Error message- null
           2019-05-31 18:15:08.906 ERROR 6972 --- [nio-8080-exec-4] c.t.s.r.GlobalExceptionHandler           : Error message string- java.lang.NullPointerException
           2019-05-31 18:15:08.907  INFO 6972 --- [nio-8080-exec-4] c.t.s.r.GlobalExceptionHandler           : ERROR response JSON- {"type":"Error","status":"fail","status_code":0,"user_message":"Internal Server Error! Please contact Administrator"}

Questions:

  1. Не удается сохранить данные после применения триггера к таблице базы данных?

  2. Есть ли возможное решение для аннотации @Transaction, используемой в классе обслуживания?

Ошибка возникает после добавления аннотации @Trasactional ккласс обслуживания.

...