What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Short answer: underscores are valid in SQL column names and in JPA mappings. The usual failure is in a Spring Data derived query method: Spring Data parses the method name as a path of Java entity properties, and _ is reserved syntax for marking nested-property traversal. Keep Java properties in camelCase, map them to snake_case columns with @Column or a verified naming strategy, and use a doubled underscore only when a literal underscore in a Java property cannot be changed.

The three names involved

A single attribute can have different names at different layers:

Layer Example Interpreted by
Java entity property employeeCode Java, Spring Data and Hibernate
JPA/Hibernate logical name employeeCode (unless explicitly mapped) JPA/Hibernate metadata
Physical database column employee_code Database and generated SQL

Spring Data validates a derived repository method against the managed entity’s properties. It does not normally look for a database column whose name happens to match the method text. Hibernate later translates the resolved property to its mapped SQL column.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For example:

@Entity
class Employee {
    @Id
    private Long id;

    @Column(name = "employee_code")
    private String employeeCode;
}

The matching method is:

Optional<Employee> findByEmployeeCode(String employeeCode);

Writing findByEmployee_Code does not normally mean “use the employee_code column.” Spring Data can read that underscore as a property-path delimiter and attempt to resolve employee followed by code. A startup error such as No property 'employee' found for type 'Employee' or a PropertyReferenceException usually indicates this parsing problem, not an invalid SQL identifier.

Why Spring Data reserves the underscore

Derived queries encode property paths in a method name. If an entity has an address association whose target has a zipCode property, both forms may express the filter:

findByAddressZipCode(String zipCode)
findByAddress_ZipCode(String zipCode)

The underscore makes the intended traversal explicit: address → zipCode. Because that character has syntax, a literal underscore in a Java property is ambiguous. Spring Data’s property-expression rules therefore recommend camel-case property names and reserve _ for path disambiguation.

The preferred mapping pattern

Keep the Java model idiomatic and isolate the legacy or snake_case schema in mapping metadata:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
@Entity
@Table(name = "customer")
public class Customer {
    @Id
    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "created_at")
    private Instant createdAt;
}

public interface CustomerRepository
        extends JpaRepository<Customer, Long> {
    List<Customer> findByFirstName(String firstName);
    List<Customer> findByFirstNameAndLastName(String firstName, String lastName);
    List<Customer> findByCreatedAtAfter(Instant timestamp);
}

Here, repository methods refer to firstName and lastName; Hibernate generates SQL using first_name and last_name. This keeps refactoring, IDE navigation and query parsing predictable.

If the Java property really contains an underscore

When a legacy model cannot be renamed, Spring Data documents a doubled underscore as the escape notation:

class LegacyRecord {
    private String first_name;
}

interface LegacyRecordRepository
        extends JpaRepository<LegacyRecord, Long> {
    List<LegacyRecord> findByFirst__name(String value);
}

__ represents a literal underscore in the property name. It is a supported compatibility technique, but it is easy to misread, couples every derived query to an awkward Java naming convention, and becomes harder to maintain as paths grow. Rename the Java property and use @Column(name = "first_name") whenever that is practical.

Where naming strategies fit

Hibernate separates naming into an implicit stage (choosing a logical name when none is supplied) and a physical stage (turning that logical name into the database identifier). A physical strategy can convert employeeCode to employee_code; Hibernate describes this through naming strategies and the PhysicalNamingStrategy API.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Current Spring Boot documentation commonly uses CamelCaseToUnderscoresNamingStrategy as the physical strategy, but the result depends on the Spring Boot/Hibernate version, explicit annotations, dialect and custom configuration. A typical configuration is:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy

Do not copy obsolete properties such as spring.jpa.hibernate.naming-strategy without checking your version. Explicit @Column and @Table names participate in Hibernate’s logical-to-physical naming pipeline; behavior can still vary with a configured strategy. When an exact identifier matters, inspect generated SQL or DDL rather than assuming an annotation always bypasses every transformation.

Choose the approach

Situation Best first choice
Snake_case schema and Java names can change CamelCase properties plus explicit @Column
Large, consistently snake_case schema owned by your team A verified physical naming strategy
Java property with a literal underscore cannot change Derived method with __
Irregular legacy names or reserved words Explicit @Column/@JoinColumn
Complex or dynamic filtering @Query, Specification or Criteria API
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When derived methods are not the right tool

JPQL still uses entity properties:

@Query("""
       select c from Customer c
       where c.firstName = :name
       """)
List<Customer> searchByFirstName(@Param("name") String name);

Using c.first_name in JPQL is wrong because that is a physical column name. A native query deliberately addresses the database schema instead:

@Query(value = """
       select * from customer
       where first_name = :name
       """, nativeQuery = true)
List<Customer> searchNative(@Param("name") String name);

For optional filters, joins, grouping, subqueries or database-specific expressions, use a specification, Criteria API or another query builder. These alternatives still target entity attributes unless the query is native.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical troubleshooting checklist

  1. Locate the failure phase. A repository-construction exception means Spring Data could not resolve a property path. A SQL execution error points instead to schema drift, a wrong mapping, permissions, a schema/quoting issue or a native query.
  2. Compare the method with the entity. Check spelling, capitalization, boolean conventions (active versus isActive), the repository’s generic entity type and whether the property is persistent.
  3. Interpret underscores correctly. Decide whether user_profile_id is meant to be one property or the path user → profile → id. Add a single underscore only for intentional nested traversal; use __ only for a literal underscore.
  4. Check access type. Hibernate can use field or property access. An @Id on a field generally implies field access; an @Id on a getter implies property access. Keep mapping annotations consistently on the selected access location, as explained in Hibernate’s access-strategy documentation.
  5. Verify the mapping and strategy. Confirm @Column/@JoinColumn, active implicit and physical strategies, and the Boot/Hibernate versions.
  6. Inspect generated SQL in development. Settings such as spring.jpa.show-sql=true and spring.jpa.properties.hibernate.format_sql=true can reveal the actual table and column names. Use normal controlled logging in production and avoid exposing bind values.
  7. Check the database separately. Verify migrations, schema selection, quoted case-sensitive identifiers and environment-specific configuration before changing a repository method that already parses successfully.

Common misconceptions

  • “JPA does not support underscores.” False. JPA and Hibernate routinely map to first_name, created_at and similar columns.
  • “The repository method should use the column name.” Usually false. Derived methods use Java entity properties; mappings translate them to SQL names.
  • “Double underscores are the best fix.” They are an escape hatch for an unavoidable literal underscore, not the preferred model design.
  • “Every naming-strategy property is interchangeable.” No. Configuration keys and defaults are version-sensitive; consult the applicable Spring Boot data-access documentation.

Practical rule: use camelCase for Java entity properties, map those properties to snake_case with explicit annotations or a verified physical naming strategy, and reserve underscores in repository methods for deliberate path traversal.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.