Java 如何在Spring数据JDBC中编写自定义@Query?
在SpringDataJDBC示例中,如何在Java 如何在Spring数据JDBC中编写自定义@Query?,java,spring,spring-data,spring-data-jdbc,Java,Spring,Spring Data,Spring Data Jdbc,在SpringDataJDBC示例中,如何在@query注释中编写一个简单的查询 e、 在中,如何添加一个简单的findByName查询 当我试着 @Query(“从乐高设置中选择*,其中name=:name”) 列出findByName(@Param(“name”)字符串名); 它抛出以下错误: org.springframework.data.mapping.MappingException: Could not read property @org.springframework.dat
@query
注释中编写一个简单的查询
e、 在中,如何添加一个简单的findByName
查询
当我试着
@Query(“从乐高设置中选择*,其中name=:name”)
列出findByName(@Param(“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中还不存在的派生查询。LegoSet实体与
手册有1:1的关系。
Spring数据JDBC使用联接选择这样的构造,并期望ResultSet
中具有代表性的列
请注意,它需要表示手册
实体本身的列加上构成LegoSet
的反向引用的列。
此外,所有列名的前缀都应为属性名+。
,即在这种情况下为手动
错误消息实际上告诉您缺少的列(以缺少的空格为单位):未找到列:manual\u handbuch\u id
或者
关于文件:
你说得有点对。
(几乎)所有Spring数据模块的文档都包含一个容易导致混淆的通用部分。有。我认为您正在尝试执行本机查询。因此,请尝试以下操作
@Query( value = "SELECT * FROM lego_set ls where ls.name = :name",
nativeQuery = true)
List<LegoSet> findByName(@Param("name") String name);
@Query(value=“SELECT*FROM lego_set ls where ls.name=:name”,
nativeQuery=true)
列出findByName(@Param(“name”)字符串名);
这应该行得通。就像@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);
@Query(“选择ls.id、ls.name、ls.min\u age、ls.max\u age,”+
“h.handbuch\u id作为手动\u handbuch\u id,h.author作为手动\u作者,h.text作为手动\u文本”+
“从乐高设置ls在ls.id=h.handbuch\U id上加入handbuch h”+
“其中name=:name”)
列出findByName(@Param(“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");
}
@测试
公开作废so_52978700(){
//预备
LegoSet cars=createLegoSet(“小汽车-01”,5,10);
设置手册(新手册(“只要把所有的部件按正确的顺序放在一起”,“Jens Schauder”);
储存库。保存(汽车);
//执行
List-actual=repository.findByName(“Small-Car-01”);
//核实
资产(实际)价值(1);
assertThat(actual.get(0.getName()).isEqualTo(“Small-Car-01”);
assertThat(actual.get(0.getManual().getText()).isEqualTo(“只要把所有的部分按正确的顺序放在一起就行了”);
}
您可能需要设置nativeQuery=true。reference@user1211Spring数据JDBCs@Query
注释中没有nativeQuery
属性,因为所有查询都是以所用数据库的本地SQL方言提供的。这是指Spring数据jdbc,而不仅仅是Spring数据jpa,因此nativeQuery无法工作。从日志中,我可以看到默认findAll()的本地查询类似于你提到的,我用plus-where子句替换了我的查询,这是有效的。但不确定命名约定,如手动\u handbuch\u id。还注意到,对于1对多,它是在单独的查询中实现的。我希望它也能在1对1上运行。对于更复杂的情况,1对1子类有自己的1对1子类,等等,那么编写SQL将是非常繁琐和容易出错的。我同意。如果你有办法减轻痛苦,请制作一张罚单。同时,我想我的期望是人们经常使用自定义的行映射器来处理非琐碎的事情。在内部实现中将1对1与1对多等同起来有多困难?如果只是出于性能原因,那么至少将其作为一个选项提供会更好。另一种方法是提供派生查询作为其他Spring数据,这些数据应该覆盖我们90%以上的案例。我记得你在你的研讨会上提到它正在进行中?希望你能很快看到。谢谢。参加1:很多事情都会发生。查询派生也是如此。我想让编写自定义查询变得更容易。我想我还没有完全理解示例中的btw手册和模型的区别。它们都是聚合的一部分,为什么在\@查询中我必须专门处理手动而不是模型?理想情况下,我不需要担心\@查询中的子对象。