英文:
SQLGrammarException: could not prepare statement
问题
我有一个使用Spring Boot的应用程序,其中使用CrudRepository访问h2数据库。
public interface PetRepository extends CrudRepository<PetBE, Long> {
@Query("SELECT p FROM PetBE p INNER JOIN TagBE t WHERE t.name IN :tags")
public List<PetBE> findPetsByAnyTag(@Param("tags") List<String> tags);
}
我的实体类如下:
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "pets")
public class PetBE {
@Id
private long id;
@NonNull
private String name;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "category_id", referencedColumnName = "id")
private CategoryBE category;
@NonNull
@ElementCollection
private List<String> photoUrls;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "pet_tags",
joinColumns = @JoinColumn(name = "pet_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
@OrderColumn(name = "id")
private List<TagBE> tags;
@Enumerated(EnumType.STRING)
private StatusEnum status;
}
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name = "tags")
public class TagBE {
@Id
@NonNull
private long id;
@NonNull
private String name;
@ManyToMany
private List<PetBE> pets;
}
但是当我调用我的方法时,我收到以下错误:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select petbe0_.id as id1_4_, petbe0_.category_id as category4_4_, petbe0_.name as name2_4_, petbe0_.status as status3_4_ from pets petbe0_ inner join tags tagbe1_ on where tagbe1_.name in (?)]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "SELECT PETBE0_.ID AS ID1_4_, PETBE0_.CATEGORY_ID AS CATEGORY4_4_, PETBE0_.NAME AS NAME2_4_, PETBE0_.STATUS AS STATUS3_4_ FROM PETS PETBE0_ INNER JOIN TAGS TAGBE1_ ON WHERE[*] TAGBE1_.NAME IN (?)]"; expected "NOT, EXISTS, INTERSECTS, UNIQUE"; SQL statement:
select petbe0_.id as id1_4_, petbe0_.category_id as category4_4_, petbe0_.name as name2_4_, petbe0_.status as status3_4_ from pets petbe0_ inner join tags tagbe1_ on where tagbe1_.name in (?) [42001-200]
我不知道接下来该怎么办,语法看起来对我来说没问题。
而且查询在编译时是可以通过的,错误只在运行时出现。
我在这里漏掉了什么?
英文:
I have a spring boot application with an h2 database that is addressed by a CrudRepository.
public interface PetRepository extends CrudRepository<PetBE, Long> {
@Query("SELECT p FROM PetBE p INNER JOIN TagBE t WHERE t.name IN :tags")
public List<PetBE> findPetsByAnyTag(@Param("tags") List<String> tags);
}
My Entities are as follows
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "pets")
public class PetBE {
@Id
private long id;
@NonNull
private String name;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "category_id", referencedColumnName = "id")
private CategoryBE category;
@NonNull
@ElementCollection
private List<String> photoUrls;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "pet_tags",
joinColumns = @JoinColumn(name = "pet_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
@OrderColumn(name = "id")
private List<TagBE> tags;
@Enumerated(EnumType.STRING)
private StatusEnum status;
}
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name = "tags")
public class TagBE {
@Id
@NonNull
private long id;
@NonNull
private String name;
@ManyToMany
private List<PetBE> pets;
}
But when I call my method I get:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select petbe0_.id as id1_4_, petbe0_.category_id as category4_4_, petbe0_.name as name2_4_, petbe0_.status as status3_4_ from pets petbe0_ inner join tags tagbe1_ on where tagbe1_.name in (?)]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "SELECT PETBE0_.ID AS ID1_4_, PETBE0_.CATEGORY_ID AS CATEGORY4_4_, PETBE0_.NAME AS NAME2_4_, PETBE0_.STATUS AS STATUS3_4_ FROM PETS PETBE0_ INNER JOIN TAGS TAGBE1_ ON WHERE[*] TAGBE1_.NAME IN (?)"; expected "NOT, EXISTS, INTERSECTS, UNIQUE"; SQL statement:
select petbe0_.id as id1_4_, petbe0_.category_id as category4_4_, petbe0_.name as name2_4_, petbe0_.status as status3_4_ from pets petbe0_ inner join tags tagbe1_ on where tagbe1_.name in (?) [42001-200]
I don't know where to go from here the grammar looks fine to me.
Also the query does compile, the error comes only at runtime.
What am I missing here?
答案1
得分: 3
通过不使用定义好的关联,你引入了交叉连接(但是期望是内连接)。你可以在生成的查询片段中看到:
内连接 tags tagbe1_ on where tagbe1_.name in (?)
^
你可以通过使用第二个实体作为第一个实体的字段来修复这个问题:
@Query("SELECT p FROM PetBE p INNER JOIN p.tags t WHERE t.name IN :tags")
public List<PetBE> findPetsByAnyTag(@Param("tags") List<String> tags);
英文:
By not using the defined relationship you're introducing the cross join (but inner join is expected). You can see it in the following fragment of the generated query:
inner join tags tagbe1_ on where tagbe1_.name in (?)
^
You can fix this by using the second entity as the field of the first one:
@Query("SELECT p FROM PetBE p INNER JOIN p.tags t WHERE t.name IN :tags")
public List<PetBE> findPetsByAnyTag(@Param("tags") List<String> tags);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论