SQL语法异常:无法准备语句

huangapple go评论124阅读模式
英文:

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&lt;PetBE, Long&gt; {

	@Query(&quot;SELECT p FROM PetBE p INNER JOIN TagBE t WHERE t.name IN :tags&quot;)
	public List&lt;PetBE&gt; findPetsByAnyTag(@Param(&quot;tags&quot;) List&lt;String&gt; tags);
}

My Entities are as follows

@Data
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = &quot;pets&quot;)
public class PetBE {
	
	@Id
	private long id;

	@NonNull
	private String name;

	@ManyToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = &quot;category_id&quot;, referencedColumnName = &quot;id&quot;)
	private CategoryBE category;
	
	@NonNull
	@ElementCollection
	private List&lt;String&gt; photoUrls;
	
	@ManyToMany(cascade = CascadeType.ALL)
	@JoinTable(
		name = &quot;pet_tags&quot;, 
		joinColumns = @JoinColumn(name = &quot;pet_id&quot;), 
		inverseJoinColumns = @JoinColumn(name = &quot;tag_id&quot;))
	@OrderColumn(name = &quot;id&quot;)
	private List&lt;TagBE&gt; tags;
	
	@Enumerated(EnumType.STRING)
	private StatusEnum status;

}

@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name = &quot;tags&quot;)
public class TagBE {

	@Id
	@NonNull
	private long id;
	
	@NonNull
	private String name;
	
	@ManyToMany
	private List&lt;PetBE&gt; 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 &quot;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 (?)&quot;; expected &quot;NOT, EXISTS, INTERSECTS, UNIQUE&quot;; 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(&quot;SELECT p FROM PetBE p INNER JOIN p.tags t WHERE t.name IN :tags&quot;)
public List&lt;PetBE&gt; findPetsByAnyTag(@Param(&quot;tags&quot;) List&lt;String&gt; tags);

huangapple
  • 本文由 发表于 2020年10月19日 08:09:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/64419548.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定