我在实体属性名称中有下划线,当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
答案 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();