@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


Проблема явно в вызове Репозиториев. А вот почему, не могу понять.
  • Вопрос задан
  • 472 просмотра
Решения вопроса 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();
        }
    }

}


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

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

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽