How to add extra parameter to all queries in Repository - spring

I'm letting system to create queries from the methods names:
public interface CompanyRepository extends JpaRepository<Company, Long> {
Boolean existsByName(String name);
Boolean existsByRegCode(String regCode);
}
There are several different repos for different entities (Company, User, Shop) and they all have field named CountryId.
Now I need to add condition "AND CountryId = :CountryId" to all queries in all repos , where the country parameter gets it's value from some configuration file.
I know that I should build some base class for this and extend from that, but can't figure out what to put into this class.

You can define a superclass for all of your entities and add the countryId field to this superclass and annotate with #Where(clause = "countryId='id'")
#Where(clause = "countryId='id'")
public class Entity {...}
and
public class Company extends Entity {...}

Related

Spring Data JPA - findBy mapped object

In my legacy application, I have a country table, state table and a mapping table for country and state with few additional columns.
I have created an entity class like this.
class CountryStateMapping {
#Id
private long id;
private Long countryId;
#OneToOne
#JoinColumn(name="state_id")
private State state;
//getters seters
}
My repository.
public interface CountryStateMapping extends JpaRepository<CountryStateMapping, Long>{
Optional<CountryStateMapping> findByStateId(long stateId);
Optional<CountryStateMapping> findByState(State state);
}
I would like to check if the state exists in the mapping table. Both of the below approaches do not work.
countryStateMapping.findByStateId(long stateId)
countryStateMapping.findByState(State state)
What is the right way?
Its not the correct way i feel.The correct way for doing this will be
public interface CountryStateMappingRepository extends JpaRepository<CountryStateMapping, Long> {
Optional<CountryStateMapping> findByStateId(long stateId);
#Query("select s.something from State s" )
Optional<CountryStateMapping> findByState(State state);
}
This implies two things
By extending JpaRepository we get a bunch of generic CRUD methods to create, update, delete, and find
2.It allows Spring to scan the classpath for this interface and create a Spring bean for it.
Also you need some configuration.For that you need to create a configuration class to be used with your data source.You can find many examples to do the same and one such is https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa.
You can also use custom queries and simple queries using the #Query annotation.
Thanks
Try with an underscore for id like below;
public interface CountryStateMapping<CountryStateMapping, Long>{
Optional<CountryStateMapping> findByState_Id(long stateId);
Optional<CountryStateMapping> findByState(State state);
}

Spring Jpa Query by Example collection

Let's say I have an entity
public class Person {
private String id;
private String firstname;
private String lastname;
private Set<Car> ownedCars;
}
Is there a way I can use query by example to find any person named James having both a Ferrari and Lamborghini?
If I use:
Person p = new Person();
p.setName("James");
p.getOwnedCars.addCar(new Car("Lamborgnihi"));
p.getOwnedCars.addCar(new Car("Ferrari"));
Example<Person> exampleOfPerson = Example.of(p);
List<Person> foundPersons = personRepository.finaAll(exampleOfPerson);
it seems it queries only on person's attributes and ignores any child collections.
You can use a query method for that. Let's say your Car has a property name that can be "Lamborghini" or "Ferrari"
interface PersonRepository extends JpaRepository<Person, String> {
List<Person> findByOwnedCarsNameIn(Collection<String> names);
}
Then you use it like this:
personRepository.findByOwnedCarsNameIn(Arrays.asList("Ferrari","Lamborghini"));
Some gotchas:
The method parameter can take any subclass of Collection, or an array.
The property names on Person and Car must match the method signature and the parameter name as shown above for spring to know how to generate the query, i.e. Person must have a property called "cars", and Car must have a property called "name".
I used JpaRepository, but this works with any of the Repository interfaces provided with spring data JPA

How to Define Dynamic Model in Spring Framework

I am using Spring Framework as my back end
I have define know as Entity class The Entity class know contain 5 Fields
Below is the class , The code below dose not have setter getter part to make shorter and cleaner
#Entity
#Table(name="TblKnow")
public class Know {
#Id
private Double idKnow;
private String SubjectKnow;
private String BodyKnow;
private String ImgKnow;
private double CountView;
In JpaRepository interface i want to only query two column not all of columns.
public interface KnowRepository extends JpaRepository<Know,Double> {
#Query("SELECT idKnow,SubjectKnow FROM Know")
public Page<Know> findCByOrderByIdKnowDesc(Pageable pageable);
Problem: i try to run but i get below exception
java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type [java.lang.Long]
But if i use without below query it is fine
public Page<Know> findAllByOrderByIdKnowDesc(Pageable pageable);
You can create a custom constructor and use that to select only some fields in JPA query.
public Know(Double idKnow, String SubjectKnow) {
this.idKnow = idKnow;
this.SubjectKnow = SubjectKnow;
}
And the use this constructor in JPA query. Make sure you use complete path of class with package.
#Query("SELECT NEW packagePath.Know(idKnow,SubjectKnow) FROM Know")
query :
public Page<Know> findAllByOrderByIdKnowDesc(Pageable pageable);
works dut to you select Know objects with fields that are mapped correct into Know class (and after wrapped into Page).
with query :
#Query("SELECT idKnow,SubjectKnow FROM Know")
public Page<Know> findCByOrderByIdKnowDesc(Pageable pageable);
returns some custome bean/object that spring data can't map in correct way into Know class (as you declared it as expected return class wrapped into Page). add counstructor into Know with idKnow,SubjectKnow fields , or you can wrap it into some DTO with idKnow,SubjectKnow fields.

spring data rest hateoas dynamically hide repository

I'm still trying to figure what exactly it is I am asking but this is fallout from a discussion in the office. So the dilemma is that on a mapping set to eager with a repository defined for the entity the mapping is to, a link is produced. Some of the time that is fine but some of the time I'd rather have the object fetched itself. If there is not a repository defined for that entity then that is what will occur with the eager fetch strategy. What would be ideal is if I could pass in a parameter and have the existence of that repository disappear or reappear.
Not totally following, but either the repo exists or not. If you want to be able to access entities of type X independently of other entity types, then you have to define a repo for type X.
I think you could achieve something similar using projections.
So you define define a repository for your association entity. By default spring data rest will just render a link to this entity and not embed it in the response.
Then you define a projection with a getter for your associated entity. You can choose on the client side if you want the projection by adding the projection query parameter.
So lets say you have a person with an address - an exported repository exists for Person and Address:
#Entity
public class Person {
#Id #GeneratedValue
private Long id;
private String firstName, lastName;
#OneToOne
private Address address;
…
}
interface PersonRepository extends CrudRepository<Person, Long> {}
interface AddressRepository extends CrudRepository<Address, Long> {}
Your projection could look like this:
#Projection(name = "inlineAddress", types = { Person.class })
interface InlineAddress {
String getFirstName();
String getLastName();
Address getAddress();
}
And if you call http://localhost/persons/1?projection=inlineAddress you have the address embedded - and by default it is just linked.

Spring Data Repository query hook

In Spring Data is it possible to extend a query that is generated by the find* functions of the repo interfaces?
Given following use case:
My legacy database has an inheritance by table. So given following
#Entity public class Person {
private int id;
private String className;
}
#Entity #PrimaryKeyJoinColumn(name="id") public class Musician extends Person {
String instrument;
}
#Entity #PrimaryKeyJoinColumn(name="id") public class Lawyer extends Person {
String discipline;
}
My repository for Musician:
public interface MusicianRepository extends CrudRepository<Musician, int> {
List<Musician> findAll();
}
Now an entry for a new musician in SQL would be:
insert into Person(id, className) values(1, 'Musician');
insert into Musician(id, instrument) values(1, 'piano');
When a Musician got migrated to a lawyer the old system added one row to Lawyer table without removing Musician by:
insert into Lawyer(id, discipline), values(1, 'finance');
update Person set ClassName = 'Lawyer' where ID = 1;
My MusicianRepo would now find the lawyer since the row in Musician still exists.
I would need some kind of post processor where I could extend the query by adding a where clause with "ClassName = 'Musician'" on all find* methods.
Is this possible somehow?
I think that your JPA mapping is just not correct in terms of inheritance.
I think you want to have "Joined, Multiple Table Inheritance"
Citing from here:
Joined inheritance is the most logical inheritance solution because it
mirrors the object model in the data model. In joined inheritance a
table is defined for each class in the inheritance hierarchy to store
only the local attributes of that class. Each table in the hierarchy
must also store the object's id (primary key), which is only defined
in the root class. All classes in the hierarchy must share the same id
attribute. A discriminator column is used to determine which class the
particular row belongs to, each class in the hierarchy defines its own
unique discriminator value.
Some JPA providers support joined inheritance with or without a
discriminator column, some required the discriminator column, and some
do not support the discriminator column. So joined inheritance does
not seem to be fully standardized yet.
The className column in Person would be your descriminator column. It determines the subclass to instantiate.
Your mapping would be something like this:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="className")
public class Person {
private int id;
private String className;
}
#Entity
#DiscriminatorValue("Musician")
public class Musician extends Person {
String instrument;
}
#Entity
#DiscriminatorValue("Lawyer")
public class Lawyer extends Person {
String discipline;
}
This way if you query for Lawyer entities JPA would automatically add the where clause to just read rows with className=Lawyer
I did not try the mapping - it should just illustrate the way you should be going.

Resources