Search code examples
javahibernatespring-bootjpa

JPA use repository findBy with an entity object


I'm trying to create a spring boot application, and I would like to set up a research feature.

What I've done so far :

I have two classes, Person.java and House.java with a OneToOne relationship between these two classes. I'd like to create a research function which allows me to find a Person depending on the House properties. For exemple find all persons who have houses with zipcode "45000" and city "ORLEANS". For this I've declared a function in my repository findByHouseZipcodeAndCity.

Now, the problem is that my House entity has about 15 properties, and I want to perform researches with any of these 15 properties : zipcode only, zipcode and city, city and surface... which makes a lot of combinations, and I don't want to create findBy methods for each combination.

I've tried to give as a parameter to my findBy a House object which will contain the search criterias. This is not working as hibernate throws me this error : object references an unsaved transient instance - save the transient instance before flushing. The problem is that I'm creating an instance of a House, I fill it with my search criterias, and I use it for my findBy, but I found the findBy makes a flush(), while the House entity is not saved (And I don't want it to be saved since it's only for a search).

I've found solutions like using JPA Criterias, but I'd like to know if I can perform my search just by using an entity as a parameter for a findBy method.

Thank you in advance for your help

PersonRepository.java

@Repository
public interface PersonRepository extends JpaRepository<Person, Long>{
    List<Person> findByHouseZipcodeAndHouseCity(String zipcode, String city);
    List<Person> findByHouse(House house);
}

Person.java

@Entity
public class Person{

    @Id
    @SequenceGenerator(name = "INFO_ACTION_SEQ", sequenceName = "INFO_ACTION_SEQ")
    @GeneratedValue(generator = "INFO_ACTION_SEQ", strategy = GenerationType.AUTO)
    @Column(name = "ID_PERSON", columnDefinition = "INTEGER")
    private Integer id;

    private String name;

    private String surname;

    @OneToOne(cascade = CascadeType.ALL)
    private House house;

}

House.java

@Entity
public class House{

    @Id
    @SequenceGenerator(name = "INFO_ACTION_SEQ", sequenceName = "INFO_ACTION_SEQ")
    @GeneratedValue(generator = "INFO_ACTION_SEQ", strategy = GenerationType.AUTO)
    @Column(name = "ID_HOUSE", columnDefinition = "INTEGER")

    private Integer id;

    private String city;
    private String street:
    private String zipcode;
    private String country;
    // Other properties...
}

Solution

  • You could use query by example, a user-friendly querying technique that allows dynamic query creation and does not require you to write queries at all.

    Consider the following entity:

    @Data
    @Entity
    public class Person {
    
        @Id
        private String id;
        private String firstname;
        private String lastname;
        private Address address;
    }
    

    To search all persons with a given name, you can use:

    Person person = new Person();
    person.setFirstname("Dave");
    
    Example<Person> example = Example.of(person);
    Iterable<Person> searchResult = repository.findAll(example);
    

    And, if you need to search for a single person, use:

    Person searchResult = repository.findOne(example);