Reputation: 4889
I have a map property in my domain class and I'm attempting to create a query in the repository or use the default "findByBlah" syntax to pull property from database. Will not work currently. I can easily write the query in SQL but I have no idea what JPQL expects. How can I pull this data from database using JPQL or the interface "findBy" syntax? No matter which repository method I current use, when it pulls the "Collector" from the database, the attribute (map or list of complex object) is always null.
Domain Object:
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "collector")
public class Collector {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "collector_id")
private Long id;
@NotNull
private String name;
@ElementCollection
@MapKeyColumn(name = "attribute_name")
@Column(name = "attribute_value")
@CollectionTable(name = "collector_attributes", joinColumns = @JoinColumn(name = "collector_id"))
private Map<String, String> attributes;
@Override
public String toString() {
return ObjectUtil.print(this);
}
}
Repository:
public interface CollectorRepository extends PagingAndSortingRepository<Collector, Long> {
@Query(value = "select c from Collector c where c.attributes[$1] = $2")
Page<Collector> findByAttributesNameAndValue(String name, String value, Pageable pageable);
}
Here is the query that works in the H2 Console:
SELECT * FROM Collector a INNER JOIN collector_attributes b ON a.collector_id = b.collector_id where b.attribute_name= 'nickName' and b.attribute_value = 'Critikon'
Upvotes: 0
Views: 652
Reputation: 3166
The only this is working to me is to define an Object relation instead of a map:
@ElementCollection
@CollectionTable(name = "COLLECTOR_ATTRIBUTES", joinColumns = @JoinColumn(name = "COLLECTOR_ID"))
private List<CollectorAttribute> attributes;
And the enbedded object
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Embeddable
public class CollectorAttribute {
@Column(name = "ATTRIBUTE_NAME")
private String key;
@Column(name = "ATTRIBUTE_VALUE")
private String value;
}
now you can query using properties of embedded object
public interface CollectorRepository extends JpaRepository<Collector, Long> {
List<Collector> findByAttributesKeyAndAttributesValue(String key, String value);
}
To retrieve COLLECTOR_ATTRIBUTES
in select we can define a @NamedEntityGraph
in Collector
class and repository method as follows
@NamedEntityGraph(name = "Collector.attributes",
attributeNodes = @NamedAttributeNode("attributes"))
@Entity
@Table(name = "COLLECTOR")
public class Collector {
and report @EntityGraph
in Repository method
public interface CollectorRepository extends JpaRepository<Collector, Long> {
@EntityGraph(value = "Collector.attributes", type = EntityGraph.EntityGraphType.LOAD)
List<Collector> findByAttributesKeyAndAttributesValue(String key, String value);
}
}
Now you have also attributes
If you want to load attributes also on other methods, you have to use @EntityGraph
@EntityGraph(value = "Collector.attributes", type = EntityGraph.EntityGraphType.LOAD)
Optional<Collector> findById(Long var1);
Upvotes: 1