Reputation: 5031
I have two tables: ProductUsage and Learner. ProductUsage have field Learner, Learner has fields id and guid. now I need to create a query to pull out all productUsage whose learner guid is in specified user ids:
SQL:
select * from product_usage
inner join learner
on product_usage.learner_id = learner.id
where
learner.guid in ("1234", "2345")
domain class:
@Data
@NoArgsConstructor
@Entity
@Table(name = "core_product_usage_increments")
public class ProductUsage {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne
@JoinColumn(name = "learner_id", nullable = false)
private Learner learner;
@ManyToOne
@JoinColumn(name = "learning_language_id", nullable = false)
private Language language;
}
@Data
@NoArgsConstructor
@Entity
@Table(name = "learners")
public class Learner {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "user_guid", nullable = false, unique = true)
private String guid;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
}
and repository class:
@Repository
public interface ProductUsageRepository extends CrudRepository<ProductUsage, Integer> {
@Query("SELECT p FROM ProductUsage p WHERE p.learnerGuid = :learnerGuid")
List<ProductUsage> findByLearnerGuid(String learnerGuid);
}
client class that call the repository
@Component
public class MyClient {
@Autowired
private ProductUsageRepository repository;
public MyClient(ProductUsageRepository repository) {
this.repository = repository;
}
public List<ProductUsage> getProductUageByLeanrerGuid(String learnerGuid) {
return repository.findByLearnerGuid(learnerGuid);
}
}
and my test:
@Test
public void testClient() throws Exception {
MyClient client = new MyClient(repository);
List<ProductUsage> results = client.getProductUageByLeanrerGuid("1234");
assertNotNull(result);
}
and it failed:
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: learnerGuid of: com.acme.domain.spectrum.ProductUsage [SELECT p FROM com.acme.domain.spectrum.ProductUsage p WHERE p.learnerGuid = :learnerGuid]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1364)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
it cannot recognize the 'learnerGuid' field in ProductUsage, but that's actually defined in Learner class. how can I perform the query that join multiple tables?
Upvotes: 3
Views: 18679
Reputation: 81
You do not have use a @query
like you did
@Query("SELECT p FROM ProductUsage p WHERE p.learnerGuid = :learnerGuid")
List<ProductUsage> findByLearnerGuid(String learnerGuid);
Spring JPA framework can build the query by method name itself. Try this
List<ProductUsage> findByLearnerGuid(String learnerGuid);
or
List<ProductUsage> findByLearner_guid(String learnerGuid);
as you have a relation to Learner from ProductUsage the findBy
method can traverse through the related tables and their fields. "_" gives the framework a clear indication that query by joining the Learner table where guid =?
Otherwise the framework tries below two combinations:
where learnerGuid=?
join learner where guid=?
Upvotes: 1
Reputation: 1548
ProductUsage has no learnerGuid
property, only learner
. Try
@Query("SELECT p FROM ProductUsage p WHERE p.learner.guid = :learnerGuid")
If that doesn't work, I have another tip:
@Query("SELECT p FROM ProductUsage p join p.Learner l WHERE l.guid = :learnerGuid")
Upvotes: 2