Spring-Data-Jpa 存储库 - 实体列名称上的下划线

Posted

技术标签:

【中文标题】Spring-Data-Jpa 存储库 - 实体列名称上的下划线【英文标题】:Spring-Data-Jpa Repository - Underscore on Entity Column Name 【发布时间】:2014-06-20 19:03:33 【问题描述】:

我在 spring webmvc 项目中使用 spring-data-jpa。我在我的一个实体的存储库上使用query creation 时遇到问题。您可以在下面看到我的实体、我的存储库和异常。

我的实体:

@Entity
@Table(schema = "mainschema")
@XmlRootElement
public class Municipalperson implements Serializable 

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(nullable = false)
    private Integer id;

    @Basic(optional = false)
    @Column(name = "municipal_id", nullable = false)
    private Integer municipal_id;

    @Basic(optional = false)
    @Column(nullable = false, length = 60)
    private String firstname;

    public Municipalperson(Integer id, Integer municipal_id, String firstname) 
        this.id = id;
        this.municipal_id = municipal_id;
        this.firstname = firstname;
    


    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    

    public Integer getMunicipal_id() 
        return municipal_id;
    

    public void setMunicipal_id(Integer municipal_id) 
        this.municipal_id = municipal_id;
    

    public String getFirstname() 
        return firstname;
    

    public void setFirstname(String firstname) 
        this.firstname = firstname;
    

我的仓库:

@Repository
public interface MunicipalpersonRepository extends JpaRepository<Municipalperson, Integer> 

    List<Municipalperson> findByMunicipal_idOrderByLastnameDesc(int municipal_id);

还有一个例外,

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'municipalpersonRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property municipal found for type Municipalperson!  

我尝试将 municipal_id 设置为 int,然后设置为 Integer,并且我的存储库中的参数 municipal_id 也是如此,但没有任何效果。另外,我将存储库重命名为findByMunicipalidOrderByLastnameDescfindByMunicipalIdOrderByLastnameDesc,但它也不起作用。

最后我将municipal_id重命名municipalId(删除了下划线),还重命名了getter/setter和存储库(findByMunicipalIdOrderByLastnameDesc),问题已解决

我的问题是为什么会这样?

【问题讨论】:

Spring Data JPA 严重依赖 Java 命名约定。您选择在字段和访问器名称中使用下划线来不尊重它们。这就是你被咬的原因。尊重 Java 命名约定,Spring Data JPA 会很高兴,你的代码也会更易读。并不是说可以根据需要命名该列,包括下划线。重要的是您的映射字段名称。 非常感谢您的评论。我不知道 java 命名约定。我还发现这个*** question 也对我有帮助。 【参考方案1】:

对我有用的另一种方法是使用 @JsonProperty 来区分 REST 请求/响应中使用的字段名称和用于数据库的字段名称。 例如:

@JsonProperty("municipalId")
private Integer municipal_id;

【讨论】:

当输入类型为 NON JSON 类型时不起作用,例如:application/form-urlencoded 等等.....【参考方案2】:

我知道这个问题很久以前就已经回答了,但它可以帮助将来的其他人。

根据Docs,下划线是spring用来分隔属性名的特殊字符。如果你真的想坚持蛇大小写表示法,你可以将 nativeQuery 设置为 true 并解决这个问题:

@Query(value = "SELECT * FROM municipalperson WHERE municipal_id=?1 ORDER BY last_name DESC", nativeQuery = true)
List<Municipalperson> findByMunicipal_idOrderByLastnameDesc(int municipal_id);

【讨论】:

【参考方案3】:

请将以下属性添加到 application.properties 文件中:

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

【讨论】:

这很好用,不需要其他更改。来自:docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/cfg/…:org.hibernate.cfg.ImprovedNamingStrategy 是一种改进的命名策略,它更喜欢嵌入下划线而不是混合大小写的名称。 spring.jpa.hibernate.naming-strategy 是一个未知属性错误【参考方案4】:

我通过将字段重命名为不带下划线的名称解决了这个错误。

@Column(name = "municipal_id", nullable = false)
private Integer municipalId; // <-- field was renamed

【讨论】:

这确实是处理这种情况的最佳方法,应该是公认的答案。我意识到这个答案是在问题和第一个答案之后几年出现的,但是我发表这个评论是为了引起未来访问者对这个答案的注意。以这种方式求解允许您使用以您无法控制的方式命名字段的数据库,而不会偏离 Java 开发人员整个领域普遍接受的编码标准,例如将下划线完全排除在您的方法和变量名称之外。 在不更改数据库和所有映射内容的情况下消除错误的最佳方法。 回答第一条评论时,问题不是“如何将带有下划线的 db 列名映射到 Java 实体”,而是如何使用带有下划线的实体属性和 spring-data。这就是为什么这个答案不被接受的原因。 这个答案应该被标记为正确的,这是克服问题的一个很小的努力。【参考方案5】:

下划线_ 是 Spring Data 查询派生中的保留字符(有关详细信息,请参阅reference docs),可能允许手动属性路径描述。所以你有两个选择:

    坚持 Java 命名约定,将 camel-case 用于成员变量名称,一切都会按预期工作。 使用附加下划线转义_,即将查询方法重命名为findByMunicipal__idOrderByLastnameDesc(…)

我推荐前者,因为您不会疏远其他 Java 开发人员:)。

【讨论】:

这不起作用。双下划线不会改变任何东西。 Java JPA 对象中的字段仅遵循数据库中显然不遵循 Java 约定的字段名称。所以这一定是一个很常见的用例。 双下划线解决方案对我也不起作用,我无法撤消我的支持... 双下划线对我不起作用,但我也看到很多赞成票。也许可以通过列出此方法所需的条件来改进答案,因此不适用的人不要尝试此解决方案? 答案很好。只需使用选项 1。人们花了太多时间处理约定并为其提供支持,因此它变得有用。答案的唯一问题是提到了选项 2,它不应该。 选项 1 有时是不可能的,尤其是当您使用的代码应该遵循格式指南并且验证是作为构建的一部分完成时,某些公司的一些代码约定要求您使用前缀实例变量带有“_”以将它们与方法局部变量区分开来,并避免像 this.myVar = myVar 这样的习语会变得很臭。 Jagannath 的回答涵盖了这些情况。

以上是关于Spring-Data-Jpa 存储库 - 实体列名称上的下划线的主要内容,如果未能解决你的问题,请参考以下文章

为什么Spring-Data-JPA Async无法正常工作?

使用 spring-data-jpa 自定义 ItemReader

spring-data-jpa 存储库模式与 Querydsl 查询模式有啥区别?

Spring-Data-JPA ManyToMany 与额外列的关系

处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型

spring-data-jpa 1.11.16 带游标的存储过程