Run two #NamedNativeQuery query on same entity Class - spring

I want to define two #NamedNativequery on entity class . When tying to define eclipse gives a error.
Duplicate annotation of non-repeatable type #NamedNativeQuery. Only
annotation types marked #Repeatable can be used multiple times at one
target.
From that error , I know we cannot define two define two #NamedNativeQuery of the entity class like
#Entity
#Table(name = "abc")
#NamedNativeQuery(name = "ABC.getSomeMethod1" query = "some_query",resultSetMapping ="abcDTO")//1st name query
// #NamedNativeQuery(name = "some_name" query = "some_query",resultSetMapping ="some_dto")//try to define second query , but gives error
public class ABC {
}
I am using spring repository at dao layer to called the method which bind with this query
public interface SomeInterface extends JpaRepository<ABC, Long> {
#Query(nativeQuery =true)
List<ABCDTO> getSomeMethod1(#Param("someParam1") long someParam1, #Param("someParam2") String someParam2);
}
The senario is that I want to run the 1st native sql (which run fine) query and then run the 2nd native sql query(want to run this also from same). How to solve this or What is the possible solution.
If this way I cannot run the two native sql query then is there any other to achive this.

You can define multiple named queries like this
#NamedNativeQueries({
#NamedNativeQuery(name = "ABC.getSomeMethod1"
query = "some_query",resultSetMapping ="abcDTO"
),
#NamedNativeQuery(name = "some_name"
query = "some_query",resultSetMapping ="some_dto"
)
})
Then in the business layer under the transaction you can call these two queries one after another,
If its a simple join between two entities and select and display better go with join's. Always remember to have those columns index in the Table ;)

Related

How to fetch multiple entities by a list of natural ids with Hiberate or JPA repository?

If I have a list of natural Ids, how can I fetch all the records in the DB associated with these natural Ids at once?
All I've seen are methods that let you find an entity by a natural Id, an example of one is shown below.
#Override
public Optional<T> findBySimpleNaturalId(ID naturalId) {
Optional<T> entity = entityManager.unwrap(Session.class)
.bySimpleNaturalId(this.getDomainClass())
.loadOptional(naturalId);
return entity;
}
I am looking for a method that can take a list natural Ids and fetch all the entities with these natural Ids. My current Entity has a autogenerated UUID and a naturalId and I'd like to keep it this way.
Is there something like this below
List<Song> songs = entityManager
.unwrap(Session.class)
.byMultipleSimpleNaturalIds(Song.class)
.multiLoad(songGroup.getSongIds());
// or using the repository
customRepository.findAllByNaturalId(...)
The examples you've seen are showing you how to build them yourself, as spring does not provide individual methods for you; it knows nothing about properties in your entity other than it must have an id. If you want a findAllByNaturalId method, you have to define it in the interface.
Specifying this in your customRepository:
public List<Song> findByNaturalIdIn(List<Int> naturalIds);
Spring should generate an implementation that creates a query similar to "Select s from Song s where s.naturalId In :naturalIds".
If it doesn't, just add that JPQL query string as an annotation and it will execute it for you:
#Query(value = "Select s from Song s where s.naturalId In :naturalIds")
public List<Song> findByNaturalIdIn(List<Int> naturalIds);
Or you can write your own implementation method to execute your loadOptional calls, or any query you wish, but you still must define the method in your repository.

SpringData JPA: Query with collection of entity as parameter

I have a list of entities on which I want to perform an update, I know I could update the table with list of String/Integer.. etc as the parameter with something like
#Query("update tableName i set i.isUpdated = true where i.id in :ids")
void markAsUpdated(#Param("ids") List<Integer> itemIds);
I'm trying to avoid repeated conversion of list of entities to list of Ids for making the query in DB. I know there are deleteAll and deleteInBatch commands which accept parameter as list of entities.
How do I do this in JPA Query, I tried the following but it didn't work yet.
#Modifying(flushAutomatically = true, clearAutomatically = true)
#Query("update tableName i set i.updated = true where i in :items")
void markAsUpdated(#Param("items") List<Item> items)
The query needs ids, it doesn't know how to deal with entities.
You have multiple options:
Just pass ids to the method, the client is responsible for extracting ids.
Pass entities and use SpEL for extracting ids
As suggested in the comments use a default method to offer both APIs and to delegate from one to the other.
As for the question that came up in the comments: You can move the method for extracting the id into a single method by either have relevant entities implement an interface similar to this one:
interface WithId {
Long getId();
}
Or by passing a lambda to the method, doing the conversion for a single entity:
List<ID> extractIds(List<E> entities, Function<E, ID> extractor) {
// ...
}

Find by id=1 spring data jpa

I have a table component and entity Component. I want to select id = 1 record from jpa query. Can I write 'findByIdOne' or 'findByIdEqualtoOne'? will that give me id = 1 record? Please let me know, Thanks.
No, you cannot. Refer to the Spring Data JPA documentation which documents the exact keywords that you can use.
You are free to specify the query that you want a method to execute though. Something like
#Query("select c from Component c where c.id=1")
Component findByIdOne();
I do have to put a disclaimer: by providing this solution I assume that you are really sure that ID 1 is always going to exist and will always point to exactly the same Component record in any environment that you may be running the application against. Hardcoded database IDs in your application code is not something I would ever recommend.
Direct writing the query dsl you cant, but there is a 'way' with Java 8 using default methods:
Let's say you have the query:
public interface ComponentRespository extends CrudRepository<Component, Long> {
#Query("select c from Component c where c.id=:id")
Component findById(#Param("id") Long id);
default Component findByIdOne() {
return findById(1L);
}
//eventually
default Component findByIdTwo() {
return findById(2L);
}
}
This way you can use:
private ComponentRespository componentRepository;
.....
Component componentOne = componentRepository.findByIdOne();
Component componentTwo = componentRepository.findByIdTwo();
You can use Optional<EntityName> findById(long id) or List<EntityName> findById(long id) if it's not unique.
You can use Optional<EntityName> findById(long id) or List<EntityName> findAllById if it's not unique.
We have several options:
findByIdIs(long id) or findByIdEquals(long id)

How to connect three tables using only one entity/class in Spring & Hibernate

I have only one entity which is School - a class (example). I have 7 fields in there and those fields are from 3 different tables. The first table for example is called Classroom, second is the Teachers, third is Subject. The teachers and subject table are connected by a pk: subject_id while the classroom table and teachers table are connected by classroom_id.
I tried secondary tables but it looks like it's not correct. How to connect those tables inside a single entity and write a query in the DAO IMPLementation
You should use Entity per Table.
If you need to select into non database related Model class, you can be done easily with spring-data-jpa.
After create the Model class (like School) just use the following sample to query:
class ProgrammerNameAndCity{
fields...
allArgConstructor...
}
public interface ProgrammerRepository extends JpaRepository<Programmer,Long> {
#Query(" select new com.zlrx.database.pojo.ProgrammerNameAndCity(p.name,p.address.city) " +
"from Programmer p where p.idNumber=?1")
ProgrammerNameAndCity findNameAndCityByIdNumber(String idNumber);
}
In this example the programmer has an address field (OneToOne), but you can create any kind of query, the important thing here is the constructor call of the model.
If you want to use plain sql or impl class instead of interface to query, you can use Spring's RowMapper too.
class ProgrammerNameAndCity{
fields...
allArgConstructor...
}
public interface ProgrammerRepository extends JpaRepository<Programmer,Long> {
#Query(" select new com.zlrx.database.pojo.ProgrammerNameAndCity(p.name,p.address.city) "
+ "from Programmer p where p.idNumber=?1")
ProgrammerNameAndCity findNameAndCityByIdNumber(String idNumber);
}

Can I limit the result of JPQL to just return one result?

I would like to do something like this (in Spring Data JPA) in a repository interface:
interface myRepository extends JpaRepository<A, Long> {
#Query("select a from A a where a.x = :x")
A findFirstBySomeCondition(int x);
}
But I only need the first result. (Edited: The actual query condition is much complex so I would prefer to use #Query instead of findFirst or findTop...)
I don't want to use criteria api, because it's verbose.
I don't want to use the the native query cause I will have to compose the query string manually.
So, is there an solution left though, given the restricted requirement above?
Thanks!
The results of query methods can be limited via the keywords first or top, which can be used interchangeably. An optional numeric value can be appended to top/first to specify the maximum result size to be returned.
interface myRepository extends JpaRepository<A, Long> {
#Query("select a from A a where a.x = :x")
Page<A> findFirstBySomeCondition(#Param("x") int x,Pageable pageable);
}
Impletation Class:
Page<A> results = repository.findFirstBySomeCondition(x,new PageRequest(0, 1));
A object = results.getContent.get(0);
You can use a Pageable for that. The documentation schows different ways of using it: http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.limit-query-result

Resources