如何在Spring Data JDBC中编写自定义@Query?

时间:2018-10-24 22:21:18

标签: java spring spring-data spring-data-jdbc

在Spring Data JDBC示例中,如何在@Query批注中编写简单查询?

例如在LegoSet Repository中,如何添加简单的findByName查询?

当我尝试

@Query("select * from lego_set where name = :name") List<LegoSet> findByName(@Param("name") String name); 它会引发以下错误:

org.springframework.data.mapping.MappingException: Could not read property @org.springframework.data.annotation.Id() @org.springframework.data.relational.core.mapping.Column(value=handbuch_id, keyColumn=)private java.lang.Long example.springdata.jdbc.basics.aggregate.Manual.id from result set!
...

> Caused by: org.hsqldb.HsqlException: Column not found: manual_handbuch_idat org.hsqldb.error.Error.error(Unknown Source) at org.hsqldb.error.Error.error(Unknown Source) `

此外,该参考文档似乎是从某些通用的Spring数据文档中复制过来的,因为它提到了Spring数据jdbc中尚不存在的派生查询。

3 个答案:

答案 0 :(得分:0)

LegoSet实体与Manual具有1:1关系。 Spring Data JDBC使用联接选择这种构造,并期望ResultSet中的代表列。

请注意,它期望代表Manual实体本身的列以及构成LegoSet的反向引用的列。 另外,所有列名称都应以属性名称+ _作为前缀,在这种情况下,即为manual_

该错误消息实际上告诉您有关缺少的列(以丢失的空间为模数):Column not found: manual_handbuch_id

或者,you can also provide your own RowMapper

关于文档:

您是对的。 (几乎)所有Spring Data模块的文档都包含一个通用部分,很容易引起混淆。有a ticket for comming up with a better solution

答案 1 :(得分:0)

我认为您正在尝试执行本机查询。因此,请尝试如下

@Query(  value = "SELECT * FROM lego_set ls where ls.name = :name",
           nativeQuery = true)
  List<LegoSet> findByName(@Param("name") String name);

这应该有效。

答案 2 :(得分:0)

就像@ jens-schauder的答案的补充:

查询应为:

    @Query("SELECT ls.id, ls.name, ls.min_age, ls.max_age, " +
            "h.handbuch_id AS manual_handbuch_id, h.author AS manual_author, h.text AS manual_text " +
            "FROM lego_set ls JOIN handbuch h ON ls.id = h.handbuch_id " +
            "WHERE name = :name")
    List<LegoSet> findByName(@Param("name") String name);

使用此方法通过以下测试:

    @Test
    public void so_52978700() {
        // prepare
        LegoSet cars = createLegoSet("Small Car - 01", 5, 10);
        cars.setManual(new Manual("Just put all the pieces together in the right order", "Jens Schauder"));
        repository.save(cars);

        // execute
        List<LegoSet> actual = repository.findByName("Small Car - 01");

        // verify
        assertThat(actual).hasSize(1);
        assertThat(actual.get(0).getName()).isEqualTo("Small Car - 01");
        assertThat(actual.get(0).getManual().getText()).isEqualTo("Just put all the pieces together in the right order");
    }