Igor Konoplyanko
Igor Konoplyanko

Reputation: 9374

Spring Data JPA: search value object using raw value?

I have Entity which is defined with Value Object as field:

class CustomerEntity {

  @Id
  @Column(name = "customer_id", nullable = false)
  private CustomerId customerId;

}

CustomerId is defined as Value Object:

class CustomerId implements Serializable {
  private final String value;
  //constructor, getter omitted for brewity
}

Repository is also easily defined and works well

interface CustomerRepository extends JpaRepository<CustomerEntity, CustomerId> {
   Optional<Customer> findByCustomerId(CustomerId customerId);
}

How can I define Spring Data repository that I could search for customer on cusomter_id using String value?

Optional<Customer> findByCustomerIdStartsWith(String search);

Something similar to SELECT * FROM Customers where customer_id like '?%'? As far as I can understand I need to use custom JpaExpression with @Query annotation. But I can't figure out how can I cast Value Object field to string...

UPD 1 Have found workaround but it looks a bit ugly...

@Query("FROM CustomerEntity e where concat(e.customerId, '') like ?1%")
Optional<Customer> findByCustomerIdStartsWith(String search);

UPD 2

So I have found only way to make it work - to make Value Object as @Embeddable and use it within other objects as @Embedded with @AttributeOverride. Then solutions suggested in aswers will work. As a drawback I need to make empty constructor for Value Object.

Upvotes: 2

Views: 1759

Answers (2)

Atul
Atul

Reputation: 2711

Documentation mentions findByFirstnameLike. Would findByCustomerIdLike work for you?

Also check out advanced like expressions.

The advanced like link mentions: @Query("select u from User u where u.firstname like %?1") for findByFirstnameEndsWith. So I thought it should work with

@Query("select c from Customer c where c.customerId.value like ?1%")

List<Customer> findByCustomerIdStartsWith(String id); 

I did not expand the answer earlier as another answer mentioned something very similar when I was trying to add the details. I guess it should work with equals method implemented in CustomerId

Upvotes: 2

Nikolas
Nikolas

Reputation: 44398

Use a JPQL in the @Query and navigate to CustomerId#value using an accessor. Pass a named argument into the query using @Param("search") and refer to it as :search - it also works with like 'something%' construct.

@Query(SELECT * FROM Customers c where c.customerId.value like ':search%'")
Optional<Customer> findByCustomerIdStartsWith(@Param("search") String search);

Upvotes: 2

Related Questions