为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Spring Boot 对数据库进行错误查询

使用 Spring Boot 对数据库进行错误查询

繁星点点滴滴 2023-07-19 17:31:54
我的 API 中的 @query 有一些问题。在我的数据库中,我有 1 个包含 5 列的表:id、imie、nazwisko、wiek、miasto。我正在尝试对我的数据库进行自定义查询,然后出现 -> 错误。当我像这样创建 @Query 时:@Query(value = "SELECT * FROM osoba WHERE osoba.id = :id", nativeQuery = true)结果:{    "id": 1,    "imie": "Szymon",    "nazwisko": "Markowski",    "wiek": 55,    "miasto": "Sosnowiec"}并且知道我正在尝试进行另一个查询,例如:@Query(value = "SELECT imie  FROM osoba WHERE osoba.id = :id", nativeQuery = true)现在我们开始。它会产生如下问题:2019-09-10 21:44:29.141 ERROR 8068 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'id' not found.2019-09-10 21:44:29.158 ERROR 8068 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [SELECT imie  FROM osoba WHERE osoba.id = ?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query] with root cause有任何想法吗?
查看完整描述

2 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您的问题是您的存储库不知道您返回的列类型以及如何将它们与您的实体匹配。首先,您需要更改自定义方法的返回类型,如下所示:


@Repository

public interface OsobaRepository extend JpaRepository<Osoba, Integer> {

   @Query(value = "SELECT imie FROM osoba WHERE osoba.id = :id", 

          nativeQuery = true) 

   String findNameById(@Param("id") int id);

}

现在,如果您想将结果从String转为Json,在您的OsobaServiceImpl(如果存在)中,您需要创建该类的一个实例Osoba,填充它并返回到控制器,如下所示:


@Service

public ServiceOsobaImpl implementation ServiceOsoba {


    private final OsobaRepository osobaRepository;     


    @Autowired

    public ServiceOsobaImpl(OsobaRepository osobaRepository) {

        this.osobaRepository = osobaRepository;

    }


    // your methods

    ...


    public Osoba findNameById(int id) {

        String name = osobaRepository.findNameById(id);


        Osoba osoba = new Osoba();

        osoba.setName(name);


        return osoba;

    }


}

还有另一种选择,当您使用一个字段创建简单OsobaDto并使用它时(类比之前的选项):


public OsobaDto implements Serializable {


    private String name;


    public OsobaDto() {}


    //getter and setter 

}



@Service

public ServiceOsobaImpl implementation ServiceOsoba {


    private final OsobaRepository osobaRepository;     


    @Autowired

    public ServiceOsobaImpl(OsobaRepository osobaRepository) {

        this.osobaRepository = osobaRepository;

    }


    // your methods

    ...


    public OsobaDto findNameById(int id) {

        String name = osobaRepository.findNameById(id);


        OsobaDto osobaDto = new OsobaDto();

        osobaDto.setName(name);


        return osobaDto;

    }


}

两个选项响应均为 json 格式。produces = MediaType.APPLICATION_JSON_VALUE当然,如果您在控制器方法上方指定(或拥有类似的变体)。


更新。如果您使用Osoba类并且不想看到null价值,请执行以下操作。创建新界面:


public interface OnlyName {}

下一步是将您的实体标记为@Validated并将字段注释imie为@JsonView:


@Entity

@Validated

public class Osoba {


   // your code


   @JsonView(OnlyName.class)

   private String imie;


}

和控制器:


@RestController

@RequestMapping("/api/osoba")

public class OsobaAPI {


    @Autowired

    private OsobaRepo osobaRepo;


    @JsonView(OnlyName.class)

    @PostMapping

    @RequestMapping("/getID")

    public Osoba findOsobaById(@RequestParam("id") int id){

        String name = osobaRepo.findNameById(id);

        Osoba osoba = new Osoba();

        osoba.setImie(name);

        return osoba;

    }

}


查看完整回答
反对 回复 2023-07-19
?
MMTTMM

TA贡献1869条经验 获得超4个赞

我确实像你说的那样,我有类似的东西:


@Repository

public interface OsobaRepo extends CrudRepository<Osoba, Integer> {


    @Query(value = "SELECT imie FROM osoba WHERE osoba.id = :id", nativeQuery = true)

    String findNameById(@Param("id") int id);


}

@RestController

@RequestMapping("/api/osoba")

public class OsobaAPI {


    @Autowired

    private OsobaRepo osobaRepo;


    @PostMapping

    @RequestMapping("/getID")

    public Osoba findOsobaById(@RequestParam("id") int id){

        String name = osobaRepo.findNameById(id);

        Osoba osoba = new Osoba();

        osoba.setImie(name);

        return osoba;

    }

}

@Entity

public class Osoba {


    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private int id;

    private String imie;

    private String nazwisko;

    private int wiek;

    private String miasto;


    public Osoba() {

    }


    public Osoba(String imie, String nazwisko) {

        this.imie = imie;

        this.nazwisko = nazwisko;

    }


    public Osoba(int id, String imie, String nazwisko, int wiek, String miasto) {

        this.id = id;

        this.imie = imie;

        this.nazwisko = nazwisko;

        this.wiek = wiek;

        this.miasto = miasto;

    }


    public int getId() {

        return id;

    }


    public void setId(int id) {

        this.id = id;

    }


    public String getImie() {

        return imie;

    }


    public void setImie(String imie) {

        this.imie = imie;

    }


    public String getNazwisko() {

        return nazwisko;

    }


    public void setNazwisko(String nazwisko) {

        this.nazwisko = nazwisko;

    }


    public int getWiek() {

        return wiek;

    }


    public void setWiek(int wiek) {

        this.wiek = wiek;

    }


    public String getMiasto() {

        return miasto;

    }


    public void setMiasto(String miasto) {

        this.miasto = miasto;

    }

}

POSTMAN 的原因是:


{

    "id": 0,

    "imie": "Szymon",

    "nazwisko": null,

    "wiek": 0,

    "miasto": null

}

但希望从这个查询中有理由,比如


{

    "imie": "Szymon",

}

编辑:


关于这个话题还有一个问题。如果我想获得 JSON 格式的响应,例如:“imie,”nazwisko”?我不能使用:


    @Query(value = "SELECT imie, nazwisko FROM osoba WHERE osoba.id = :id", nativeQuery = true)

    String findNameById(@Param("id") int id);


}

如果作为字符串,则导致响应。当我这样做时,我得到:


{

    "imie": null,

    "nazwisko": "IMIE, NAZWISKO"

}

也许我应该在这里使用 String[] 或创建仅具有这两个属性的新类?


查看完整回答
反对 回复 2023-07-19
  • 2 回答
  • 0 关注
  • 89 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信