Spring Data JPA 存储库方法无法识别 属性 带下划线的名称
Spring Data JPA repository methods don't recognize property names with underscores
我在实体 属性 名称中有下划线,当 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/
If your property names contain underscores (e.g. first_name) you can
escape the underscore in the method name with a second underscore. For
a first_name property the query method would have to be named
findByFirst__name(…).
我只是按照文档说的做了,但我仍然得到异常。
我不想自己写 @Query
,我的 属性 名字需要下划线,如何解决这个问题?
我使用 Spring data jpa 1.8.0.RELEASE + hibernate 4.3.9.Final
如果您可以控制 属性 命名,请避免在实体 属性 名称 中使用下划线。这将解决您的存储库问题,并将产生更清晰的代码库。在您之后处理代码的开发人员会感谢您。
请注意,这不仅仅是我的意见:Spring specifically discourages using underscores。
As we treat underscore as a reserved character we strongly advise to
follow standard Java naming conventions (i.e. not using underscores in
property names but camel case instead).
this JIRA issue 显示了为什么使用此推荐更新文档,并且删除了描述双下划线选项的部分。
我怀疑您的根本问题 是 Spring/Hibernate 没有将驼峰式 属性 名称映射到您在数据库。您真正需要的是让您的 属性 名称在 hiberate 生成的 SQL 中解释为 S_NAME。
这就是为什么你的 属性 名字中的下划线是 "required" 吗?如果是这样,有几个解决方案:
选项 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>
此命名策略会将驼峰式转换为 SNAKE_CASE。那么你的 class 看起来就像这样简单:
@Entity
public class Student {
@Id
private String sId;
private String sName;
//...getters and setters...
}
使用这些选项中的任何一个,当它创建 SQL 时,它会将列名称解析为:
S_ID
S_NAME
注意:如果你正在使用,或者可以使用Spring启动,自动配置默认会使用SpringNamingStrategy,这是hibernate改进策略的一个稍微修改的版本。您无需执行任何操作即可获得此改进的命名策略。
终点线:
在您的 属性 名称中使用驼峰式大小写,您可以使用驼峰式大小写编写您的存储库方法名称,并且您可以停止尝试争论双下划线:
@Repository
@Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findBySName(String name);
}
写双下划线,即写 findByS__Name() for 属性 name s_name 是行不通的。我已经尝试并测试过它。按照上面的答案并更改实体中现有实例变量的名称 class。只是不要更改 getter 和 setter,因为它们可能会在现有代码中使用。
如果你不能改变我的情况下的实体,那么最好使用 jpql 查询或在存储库方法之上的本机 sql 查询
@Query("select s from Student s where s.s_name=?")
List<Student> findBySName();
我在实体 属性 名称中有下划线,当 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/
If your property names contain underscores (e.g. first_name) you can escape the underscore in the method name with a second underscore. For a first_name property the query method would have to be named findByFirst__name(…).
我只是按照文档说的做了,但我仍然得到异常。
我不想自己写 @Query
,我的 属性 名字需要下划线,如何解决这个问题?
我使用 Spring data jpa 1.8.0.RELEASE + hibernate 4.3.9.Final
如果您可以控制 属性 命名,请避免在实体 属性 名称 中使用下划线。这将解决您的存储库问题,并将产生更清晰的代码库。在您之后处理代码的开发人员会感谢您。
请注意,这不仅仅是我的意见:Spring specifically discourages using underscores。
As we treat underscore as a reserved character we strongly advise to follow standard Java naming conventions (i.e. not using underscores in property names but camel case instead).
this JIRA issue 显示了为什么使用此推荐更新文档,并且删除了描述双下划线选项的部分。
我怀疑您的根本问题 是 Spring/Hibernate 没有将驼峰式 属性 名称映射到您在数据库。您真正需要的是让您的 属性 名称在 hiberate 生成的 SQL 中解释为 S_NAME。
这就是为什么你的 属性 名字中的下划线是 "required" 吗?如果是这样,有几个解决方案:
选项 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>
此命名策略会将驼峰式转换为 SNAKE_CASE。那么你的 class 看起来就像这样简单:
@Entity
public class Student {
@Id
private String sId;
private String sName;
//...getters and setters...
}
使用这些选项中的任何一个,当它创建 SQL 时,它会将列名称解析为:
S_ID
S_NAME
注意:如果你正在使用,或者可以使用Spring启动,自动配置默认会使用SpringNamingStrategy,这是hibernate改进策略的一个稍微修改的版本。您无需执行任何操作即可获得此改进的命名策略。
终点线:
在您的 属性 名称中使用驼峰式大小写,您可以使用驼峰式大小写编写您的存储库方法名称,并且您可以停止尝试争论双下划线:
@Repository
@Transactional
public interface StudentRepository extends CrudRepository<Student, String> {
List<Student> findBySName(String name);
}
写双下划线,即写 findByS__Name() for 属性 name s_name 是行不通的。我已经尝试并测试过它。按照上面的答案并更改实体中现有实例变量的名称 class。只是不要更改 getter 和 setter,因为它们可能会在现有代码中使用。
如果你不能改变我的情况下的实体,那么最好使用 jpql 查询或在存储库方法之上的本机 sql 查询
@Query("select s from Student s where s.s_name=?")
List<Student> findBySName();