33
votes

I am using spring-data-jpa on a spring webmvc project. I am facing an issue using query creation on a Repository of one of my Entities. Below you can see my Entity, my Repository and the Exception.

My Entity:

@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;
    }
}

my Repository:

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

    List<Municipalperson> findByMunicipal_idOrderByLastnameDesc(int municipal_id);
}

and the exception,

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!  

I tried to set municipal_id as int, then as Integer and the same for the parameter municipal_id on my Repository, but none worked. Also, I renamed the Repository to findByMunicipalidOrderByLastnameDesc and findByMunicipalIdOrderByLastnameDesc but it didn't work either.

Finally I renamed the municipal_id to municipalId (underscore removed) and also renamed getters/setters and the Repository (findByMunicipalIdOrderByLastnameDesc) and the issue was resolved.

My question is why this is happening?

5
Spring Data JPA heavily relies on Java naming conventions. You chose not to respect them by having an underscore in your field and accessor names. That's why you got bitten. Respect the Java naming conventions, and Spring Data JPA will be happy, and your code will be more readable as a bonus. Not that the column can be named as you want, including with underscores. What matters is your mapped field names. - JB Nizet
Thank you very much for your comment. I didn't know about the java naming conventions. I found, also, this stackoverflow question that helped me too. - George Siggouroglou

5 Answers

35
votes

The underscore _ is a reserved character in Spring Data query derivation (see the reference docs for details) to potentially allow manual property path description. So there are two options you have:

  1. Stick to the Java naming conventions of using camel-case for member variable names and everything will work as expected.
  2. Escape the _ by using an additional underscore, i.e. rename your query method to findByMunicipal__idOrderByLastnameDesc(…).

I'd recommend the former as you're not going to alienate fellow Java developers :).

50
votes

I solved this error by renaming field to the name without underscore.

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

Please add the following properties to application.properties file:

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

I know the question was answered a long time ago, but it can help others in the future.

According to the Docs, underscore is a special character used by spring to separate properties names. If you really want to stick with snake case notation, you can set nativeQuery to true and solve this problem:

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

One other approach that worked for me is to use @JsonProperty to differentiate between field name used in REST request/response and that used for database. For example:

@JsonProperty("municipalId")
private Integer municipal_id;