Spring Data JPA存储库方法无法识别带下划线的属性名称

时间:2015-05-01 07:19:27

标签: spring-data-jpa

我在实体属性名称中有下划线,当Spring尝试创建JPA存储库实现时,会导致尝试解析属性名称的异常。

实体:

@Entity
public class Student {
      @Id
      private String s_id;
      private String s_name;
      ...
}

存储库:

 @Repository
 @Transactional
 public interface StudentRepository extends CrudRepository<Student, String> {

       List<Student> findByS__name(String name);

}

例外:

org.springframework.data.mapping.PropertyReferenceException: 
No property s found for type Student

这里说http://docs.spring.io/spring-data/jpa/docs/current/reference/html/

  

如果您的属性名称包含下划线(例如first_name),则可以   使用第二个下划线转义方法名称中的下划线。对于   必须命名查询方法的first_name属性   findByFirst__name(...)。

我刚刚在文件中说过,但我仍然有例外。 我不想自己写@Query,我的属性名称需要下划线,如何解决这个问题?

我使用Spring数据jpa 1.8.0.RELEASE + hibernate 4.3.9.Final

3 个答案:

答案 0 :(得分:9)

如果您可以控制属性命名,请避免在实体属性名称中使用下划线。这将解决您的存储库问题,并将产生更清晰的代码库。处理完代码的开发人员会感谢你。

请注意,这不仅仅是我的意见:Spring specifically discourages using underscores

  

当我们将下划线视为保留字符时,我们强烈建议   遵循标准的Java命名约定(即不使用下划线)   属性名称,但改为驼峰案例。)

this JIRA issue显示了使用此推荐更新文档的原因,并删除了描述双下划线选项的部分。

我怀疑你的根本问题是Spring / Hibernate没有将驼峰案例属性名称映射到数据库中列的蛇案例名称。您真正需要的是在Hiberate生成为S_NAME的SQL中解释您的属性名称。

这就是为什么你的房产名称中的下划线是&#34; required&#34; ?如果是这样,有一些解决方案:

选项1:@Column注释

要让JPA / Hibernate映射到正确的列名,您可以明确地告诉它名称。使用注释 @Column(name="...") 告诉它在SQL中使用哪些列名。然后字段名称不受列名约束。

@Entity
public class Student {
     @Id
     @Column(name="s_id")
     private String sId;
     @Column(name="s_name")
     private String sName;

     //...getters and setters...
}

选项2:改进命名策略
或者,如果您的应用程序包含大量实体,而不是将 @Column 添加到每个属性,请将配置文件中的默认命名策略更改为hibernate improved naming strategy

<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>

此命名策略会将camelCase转换为SNAKE_CASE。然后你的课看起来就像这样简单:

@Entity
public class Student {
     @Id
     private String sId;
     private String sName;

     //...getters and setters...
}

使用其中任何一个选项,在创建SQL时,它会将列名解析为:

 S_ID
 S_NAME

注意:如果您正在使用,或者可以使用Spring Boot,则自动配置默认将使用SpringNamingStrategy,这是hibernate改进策略的略微修改版本。您不必做任何事情来获得这种改进的命名策略。

终点线:

在您的属性名称中使用camel case,您可以使用camel case编写存储库方法名称,并且可以停止尝试使用双下划线:

@Repository
@Transactional
public interface StudentRepository extends CrudRepository<Student, String> {  
       List<Student> findBySName(String name);   
}

答案 1 :(得分:4)

编写双下划线,即为属性名s_name编写findByS__Name()不起作用。我试过并测试过它。转到上面的答案并更改实体类中现有实例变量的名称。只是不要更改getter和setter,因为它们可能会在现有代码中使用。

答案 2 :(得分:3)

如果你无法更改我的情况下的实体,那么最好在存储库方法之上使用jqpl查询或本机sql查询

@Query("select s from Student s where s.s_name=?")
List<Student> findBySName();