DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Implement Hibernate Second-Level Cache With NCache
  • New ORM Framework for Kotlin
  • Angular Component Tree With Tables in the Leaves and a Flexible JPA Criteria Backend
  • Externalize Microservice Configuration With Spring Cloud Config

Trending

  • Top Tools for Front-End Developers
  • Threat Modeling for Developers: Identifying Security Risks in Software Projects
  • When MySQL, PostgreSQL, and Oracle Argue: Doris JDBC Catalog Acts as the Peacemaker
  • Automating E2E Tests With MFA: Streamline Your Testing Workflow
  1. DZone
  2. Data Engineering
  3. Databases
  4. SpringData: Property Traversal

SpringData: Property Traversal

In this article, Shamik Mitra will discuss the details of the "Queryname," derivation technique.

By 
Shaamik Mitraa user avatar
Shaamik Mitraa
·
Oct. 05, 16 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
6.8K Views

Join the DZone community and get the full member experience.

Join For Free

We are aware of the fact that if we want to create a query based on entity bean properties that are not present Repository interface (CrudRepository, JpaRepository, etc.), we can do so very easily in SpringData. We just need to declare a method in our custom Repository that must have to obey a pattern.Then, Spring data create the query for us on the fly.

The pattern is Queryname<java property><Operation>,.

In this article, we will discuss the details of this Query derivation technique. SpringData has an inbuilt data stores (JPA, MongoDB) and a specific QureyTransalorFactory that will translate the method written in the custom repository to store a specific query.

Let's say that we have a Person Entity and a Person Repository. Underlying dataStore is JPA.

package com.example.person;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Person {

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
private String country;
private String gender;

@OneToMany(mappedBy="person",targetEntity=Hobby.class,
       fetch=FetchType.EAGER,cascade=CascadeType.ALL)
List<Hobby> hobby;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}


public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}


public List<Hobby> getHobby() {
return hobby;
}
public void setHobby(List<Hobby> hobby) {
this.hobby = hobby;
}

public void addHobby(Hobby ihobby)
{
if(hobby == null)
{
hobby = new ArrayList<Hobby>();
}
hobby.add(ihobby);
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", country=" + country + ", gender=" + gender + "]";
}



}

package com.example.person;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Hobby {

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

   @ManyToOne
   @JoinColumn(name="person_id")
private Person person;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}




}


Repository 

package com.example.repo;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import com.example.person.Person;


public interface PersonRepositary extends CrudRepository<Person, Long> {

List<Person> findByCountryContains(String country);


}

Now, When QueryTranslator encounters the method findByCountryContains, it performs following steps:

  1. Strip the section findBy.

  2. Try to find an exact match for the stripped section and Person entity’s property. Because Person does not have any property called CountryContains, we go to Step 3.

  3. Again, query translator split the rest section based on camelCase pattern from the tail, so it now has two tokens (Country and Contains).

  4. Query translator tries to match Country with Person entity properties. It finds an exact match, so it's taken this phrase as one of the filter criteria.

  5. As Contains is a predefined combining criterion based on the underlying data store, query translator understands the same and has put a like check.

  6. As underlying Store is JPA, now the query translator generates a query.

Select p from person p where p.country like ?1. Spring Data’s QueryTranslator is very powerful. It can also derive a query using nested bean property.

Let's check the Person bean again. We have a mapping between Person and Hobby; it is one to many relationships. Suppose we want to create a query that  will fetch Person based on a hobby. To do this, we just have to create a method in Person repository. Now, query translator tries to find a match for  “HobbyName”. As it is not matched, again it strips this phrase to two tokens (Hobby and Name). Then, it tries to match Hobby and it finds a List in Person entity. Then, it goes into the Hobby Entity and finds a property called Name, so it creates a query like the following:

Hibernate: 
    select
        person0_.id as id1_1_,
        person0_.country as country2_1_,
        person0_.gender as gender3_1_,
        person0_.name as name4_1_ 
    from
        person person0_ 
    left outer join
        hobby hobby1_ 
            on person0_.id=hobby1_.person_id 
    where
        hobby1_.name=?

Query translator is powerful, but it has one shortcoming. Let's say we have added an additional property hobbyName in person now Query translator finds a match hobbyName in first place so it tries to filter against this property

So then query would be:

Select p from Person p where p.hobbyName=?1

...which is wrong. To overcome this situation, we can introduce a _(underscore) to demarcation the traversal path. The method name will be:

List<Person> findPersonByHobby_Name(String hobby);

Now QueryTranslator understands that Hobby and Name are two different tokens.

Property (programming) Database

Published at DZone with permission of Shaamik Mitraa, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Implement Hibernate Second-Level Cache With NCache
  • New ORM Framework for Kotlin
  • Angular Component Tree With Tables in the Leaves and a Flexible JPA Criteria Backend
  • Externalize Microservice Configuration With Spring Cloud Config

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: