@mrkovalchuk
Junior developer

Как решить проблему с подключением spring-Репозиториев?

Доброго времени суток. Проблема с... тем, не знаю, чем.
Написал кастомный метод для репозитория и простенький запрос в нем, но вот незадача: он нифига не достает мне мою запись.

В БД есть таблица room и столбец Index внутри.

Репозиторий с кастомным методом.
public interface RoomRepository extends JpaRepository<Room,Integer> {
    @Query("FROM Room b where b.index = :Index")
    Room findByIndex(@Param("Index") String index);
}


Итак, последовательно, что из чего.
Сначала у нас рест-контроллер:
@RestController
public class StartController {

    @Autowired
    private RoomService roomService;

    @RequestMapping(value = "/start", method = RequestMethod.GET)
    @ResponseBody
    public void startArduinoScan() throws SerialPortException {
        //Попробуем завести наш АрдуиноКоннектер
        ArduinoConfig arduinoConfig = new ArduinoConfig();
        arduinoConfig.arduinoConnection(roomService);
    }

    @RequestMapping(value = "/index/{index}", method = RequestMethod.GET)
    @ResponseBody
    public Room getRoomByIndex(@PathVariable String index){
        return roomService.findByIndex(index);
    }


/index/{index} работает, только там не настроена сериализация, но это к делу не относится, главное - запрос делается.

Окунаемся глубже

ArduinoConfig.java
@Configuration
@ComponentScan("com.kovalchuk.server")
@EnableJpaRepositories("com.kovalchuk.server.repository")
public class ArduinoConfig {


    private static SerialPort serialPort;

    public static SerialPort getSerialPort() {
        return serialPort;
    }


    public void arduinoConnection(RoomService roomService) throws SerialPortException {
        serialPort = new SerialPort("COM3");

        try{
            serialPort.openPort();
            serialPort.setParams(9600,8,1,0);
            serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
            serialPort.addEventListener(new ArduinoEventsListener());


        }
        catch (SerialPortException ex){
            System.out.println(ex);
        }
    }

}


Момент вызова метода.
Дата[2] - не пустое, содержит Индекс искомый.
@ComponentScan("com.kovalchuk.server")
@EnableJpaRepositories("com.kovalchuk.server.repository")
public class ArduinoEventsListener implements SerialPortEventListener {

    private SerialPort serialPort = ArduinoConfig.getSerialPort();

    @Autowired
    private CommitRepository commitRepository;

    @Autowired
    private RoomRepository roomRepository;




    @Override
    public void serialEvent(SerialPortEvent event) {
        try {
            String buffer = serialPort.readString(15);
            String[] data = buffer.split(":");

            Commit commit = new Commit();

            commit.setTemperature(Double.parseDouble(data[0]));
            commit.setWet(data[1]);
            commit.setDate(new Date());




            Room room = roomRepository.findByIndex(data[2]);

            commit.setRoom(room);

            commitRepository.save(commit);


        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }

}



Entity


package com.kovalchuk.server.entity;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

@Entity
@Table (name= "room")
public class Room {

    @Id
    @Column(name ="idRoom")
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private Long id;

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

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

    @Column(name = "Status")
    private Commit status;

    public Room(String index, String type, Commit status) {
        this.index = index;
        this.type = type;
        this.status = status;
    }

    public Room(String index, String type) {
        this.index = index;
        this.type = type;
    }

    public Room() {
    }

    public Commit getStatus() {
        return status;
    }

    public void setStatus(Commit status) {
        this.status = status;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getIndex() {
        return index;
    }

    public void setIndex(String index) {
        this.index = index;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}


Таблица Index

CREATE TABLE `room` (
  `idRoom` bigint(20) NOT NULL AUTO_INCREMENT,
  `Index` varchar(5) NOT NULL,
  `Type` varchar(5) DEFAULT NULL,
  `Status` bigint(20) NOT NULL,
  PRIMARY KEY (`idRoom`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8


Проблема явно в вызове Репозиториев. А вот почему, не могу понять.
  • Вопрос задан
  • 478 просмотров
Решения вопроса 1
jaxtr
@jaxtr
JavaEE/Spring-разработчик
У тебя в классе-сущности идентификатор типа Long, но у репозитория в дженерике указан Integer. Возможно, проблема связана с этим. А вообще да, если у тебя Spring Data JPA, то логичнее просто в интерфейсе указать метод Room findByIndex(String index); без дополнительных аннотаций.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@guras256
у тебя spring data, нафига ты писал hql запрос?
public interface RoomRepository extends JpaRepository<Room, Integer> {
    Room findByIndex(String index);
}

все что тебе нужно сделать, если в Room правильно расставлены аннотации
и да, назови поле Index с маленькой буквы...
Ответ написан
Проблема, видимо, в связи с Commit. Таблица Commit вообще содержит данные?

Может, стоит создавать Commit внутри метода serialEvent, а не как поле класса ArduinoEventListener? Кроме того, стоит прописать аннотацию ManyToOne для поля Room.status
Ответ написан
@mrkovalchuk Автор вопроса
Junior developer
см. Решение от Александр Косарев (выше)

*****************************************************************************************************
Проблему решил, но не уверен, насколько такой подход верен.

Итак, теперь я в контроллере объявляю два сервиса, которые работают с репозиториями и сую их в ArduinoConfig через новосозданный конструктор (см. ниже).

StartController
package com.kovalchuk.server.controller;

import com.kovalchuk.server.config.arduino.ArduinoConfig;
import com.kovalchuk.server.entity.Room;
import com.kovalchuk.server.services.interf.CommitService;
import com.kovalchuk.server.services.interf.RoomService;
import jssc.SerialPortException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class StartController {

    @Autowired
    private RoomService roomService;

    @Autowired
    private CommitService commitService;

    @RequestMapping(value = "/start", method = RequestMethod.GET)
    @ResponseBody
    public void startArduinoScan() throws SerialPortException {
        //Попробуем завести наш АрдуиноКоннектер
        ArduinoConfig arduinoConfig = new ArduinoConfig(roomService,commitService);
        arduinoConfig.arduinoConnection();
    }  

}


В ArduinoConfig определяю Service как поля, и добавляют два Getter-а для них. Ну и да, конструктор соответствующий нарисовал.

ArduinoConfig
package com.kovalchuk.server.config.arduino;


import com.kovalchuk.server.services.interf.CommitService;
import com.kovalchuk.server.services.interf.RoomService;
import jssc.SerialPort;
import jssc.SerialPortException;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@ComponentScan("com.kovalchuk.server")
@EnableJpaRepositories("com.kovalchuk.server.repository")
public class ArduinoConfig {


    private static SerialPort serialPort;
    private static RoomService roomService;
    private static CommitService commitService;

    public ArduinoConfig() {
    }

    public ArduinoConfig(RoomService roomService, CommitService commitService) {
        this.roomService = roomService;
        this.commitService = commitService;
    }

    public static RoomService getRoomService() {
        return roomService;
    }

    public static CommitService getCommitService() {
        return commitService;
    }

    public static SerialPort getSerialPort() {
        return serialPort;
    }


    public void arduinoConnection() throws SerialPortException {
        serialPort = new SerialPort("COM3");

        try{
            serialPort.openPort();
            serialPort.setParams(9600,8,1,0);
            serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
            serialPort.addEventListener(new ArduinoEventsListener());


        }
        catch (SerialPortException ex){
            if (serialPort.isOpened()) serialPort.closePort();
        }
    }
}


И вот так преобразился ArduinoEventsListener, который, используя гетеры, получает наши Servic-ы для работы с БД.

ArduinoEventsListener
package com.kovalchuk.server.config.arduino;


import com.kovalchuk.server.entity.Commit;
import com.kovalchuk.server.entity.Room;
import com.kovalchuk.server.services.interf.CommitService;
import com.kovalchuk.server.services.interf.RoomService;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import java.util.Date;

@ComponentScan("com.kovalchuk.server")
@EnableJpaRepositories("com.kovalchuk.server.repository")
public class ArduinoEventsListener implements SerialPortEventListener {

    private SerialPort serialPort = ArduinoConfig.getSerialPort();
    private RoomService roomService = ArduinoConfig.getRoomService();
    private CommitService commitService = ArduinoConfig.getCommitService();



    @Override
    public void serialEvent(SerialPortEvent event) {
        try {
            String buffer = serialPort.readString(15);
            String[] data = buffer.split(":");

            Commit commit = new Commit();

            commit.setTemperature(Double.parseDouble(data[0]));
            commit.setWet(data[1]);
            commit.setDate(new Date());

            Room room = roomService.findByIndex(data[2]);

            commit.setRoom(room);

            commitService.save(commit);


        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }

}


Решение позволяет записывать данные в таблицу без каких либо проблем, но вот верно ли так делать, я не знаю. Может стоило прямиком из контроллера гетерами цеплять сервисы, чтобы не протягивать их - но насколько это корректно по отношению к самому контроллеру? Работает, но вопросов все равно много.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы