How to indicate dabaseId with annotation implementation? - spring

There is a annotation query :
#Select("SELECT COUNT(*) FROM table")
public String querytableCount() throws Exception;
I want to indicate its databaseId to be postgreSQL
If the query is implemented with xml, I can make it with databaseId="postgresql":
<select id="querytableCount" resultType="String" databaseId="postgresql">
SELECT COUNT(*) FROM MCT_AGENT
</select>
How to implement the requirement base on a annotation implementation?
I have tried #DatabaseId:
#DatabaseId("PostgreSQL")
#Select("SELECT COUNT(*) FROM table")
public String querytableCount() throws Exception;
However, #DatabaseId("PostgreSQL") not work.

#Options(databaseId = "PostgreSQL") will work
Need : mybatis 3.5.5 +

Related

#Query Annotation in Spring Cassandra Repository not working

I am trying to use #Query Param for Cassandra repository in Java Springboot.
But its not working. Below is the sample code.
#Repository
public interface Table1Repository extends CassandraRepository<Table1,TransactionKey>{
#Query("SELECT * FROM table1 WHERE code=?0 and product=?1 and id=?2 order by transactiontime DESC limit ?3")
List<Table1> searchTransactionLimit(String code,String product,Double id, int limit);
}
If I hardcode the value of id within the #Query, then its working.
For example,
#Query("SELECT * FROM table1 WHERE code=?0 and product=?1 and id=17.0 order by transactiontime DESC limit ?3")
SO basically, type String and int are working in #Query. But type Double is not working.
You can try as below also but that limit number need to there in method name.
List<Table1> findTop10ByCodeAndProductAndIdOrderByTransactiontimeDesc(String code,String product,Double id);
you can try the below also by pageable.
Pageable pages = PageRequest.of(0, limit);
findByCodeAndProductAndIdOrderByTransactiontimeDesc(String code,String product,Double id,Pageable pages );

why can't I use "truncate" in spring boot

I wanna use "truncate table" statement instead of "delete" statement in spring boot project cause I need reset the auto increment id in mysql. Here is my code:
#PersistenceContext protected EntityManager em;
#Override
public void removeAllShopeeCategory() {
StringBuilder query = new StringBuilder("truncate table ShopeeCategoryDto shopeecategory");
Query q = this.em.createQuery(query.toString());
q.executeUpdate();
}
but there is an exception like this:
nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: truncate near line 1, column 1
other operation has worked, such as insert, update or select, what's the reason and what should I modify it?
Please use https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#createNativeQuery-java.lang.String- with native sql queries.
entityManager.createNativeQuery("TRUNCATE TABLE " + tableName + " CASCADE")
.executeUpdate()

select distinct values using spring data rest

I'm using java 8 and spring-data-rest to create API on my data.
I have a table Car(id, name, date...)
I'm trying to have an endpoint to retrieve distinct car names.
here's my Repository :
#RepositoryRestResource(path = "cars")
public interface CarRepository extends JpaRepository<Car, Long> {
//What i want to do
//#Query(value = "select distinct c.name as name from Car c")
#Query(value = "select distinct c from Car c")
List<Car> findDistinctName();
}
The query commented does not work , i have an exception
java.lang.IllegalArgumentException: PersistentEntity must not be null!
apparently this is the normal behavior of SDR.
I tried another solution by using Projections
#Projection(name = "name", types = {Car.class})
public interface CarName {
String getName();
}
but i cant get the distinct values, any idea?
Thank you :)
All you need, to do if you need a distinct list of cars, is such this query method:
public interface CarRepository extends JpaRepository<Car, Long> {
List<Car> findDistinctBy();
}
Spring Data JPA supports the Distinct keyword in repository query methods to set a distinct flag on the query to be created.
I found an (ugly) workaround, using jpql :
#Query(value = "select c from Car C WHERE c.id IN (SELECT min(ca.id) FROM Car ca Group by ca.name)")
I think you should remove the #Query annotation.
Just
List<Car> findDistinctName(); or List<Car> findNameDistinct(); should suffice.
It will automatically generate the query select c.name from Car c

jpql constructor expression query org.postgresql.util.PSQLException

i am using spring data jpa , i want to retrieve specific columns from postgres table, i followed couple of links to retrieve specific columns Spring JPA selecting specific columns
i found regarding jpql constructor expression query to retrieve specific columns,
i used the jpql expression on the respository class
public interface DeviceCrudRepository extends CrudRepository<Device,String>{
public Device findByBarcode(String barcode);
#Query(value = "select new com.hello.world.model.Device (d.deviceName,d.deviceType,d.deviceDescription ,d.deviceRentalStatus) from devicedetails d where d.scancode=:scancode", nativeQuery = true)
public Device findDeviceDetailsByBarcode(#Param("d.scancode") String d.scancode);
Model class is
i am using constructor too
public Device(String deviceName, String deviceType, String deviceDescription, String deviceRentalStatus) {
super();
this.deviceName = deviceName;
this.deviceType = deviceType;
this.deviceDescription = deviceDescription;
this.deviceRentalStatus = deviceRentalStatus;
}
I keep on getting exception
org.postgresql.util.PSQLException: ERROR: syntax error at or near "."
Position: 15
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2477) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2190) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169) ~[postgresql-42.1.4.jar:42.1.4]
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:117) ~[postgresql-42.1.4.jar:42.1.4]
when i checked in logs
the query which was generated was
select new com.hello.world.model.Device (d.deviceName,d.deviceType,d.deviceDescription ,d.deviceRentalStatus) from devicedetails d where d.scancode=?
it's not able to translate the jpql expression into query,it's showing exception for package name, when i use the class name it's showing exception near the brackets, so i guess the jpql expression is not being translated
am i missing any dependency any help would be appreciated?
Because PGSQL is not JPQL it's normal that it do not understand your query :) Remove the nativeQuery = true.

Spring Data: "delete by" is supported?

I am using Spring JPA for database access. I am able to find examples such as findByName and countByName, for which I dont have to write any method implementation. I am hoping to find examples for delete a group of records based on some condition.
Does Spring JPA support deleteByName-like delete? Any pointer is appreciated.
Regards and thanks.
Deprecated answer (Spring Data JPA <=1.6.x):
#Modifying annotation to the rescue. You will need to provide your custom SQL behaviour though.
public interface UserRepository extends JpaRepository<User, Long> {
#Modifying
#Query("delete from User u where u.firstName = ?1")
void deleteUsersByFirstName(String firstName);
}
Update:
In modern versions of Spring Data JPA (>=1.7.x) query derivation for delete, remove and count operations is accessible.
public interface UserRepository extends CrudRepository<User, Long> {
Long countByFirstName(String firstName);
Long deleteByFirstName(String firstName);
List<User> removeByFirstName(String firstName);
}
Derivation of delete queries using given method name is supported starting with version 1.6.0.RC1 of Spring Data JPA. The keywords remove and delete are supported. As return value one can choose between the number or a list of removed entities.
Long removeByLastname(String lastname);
List<User> deleteByLastname(String lastname);
2 ways:-
1st one Custom Query
#Modifying
#Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(#Param("firstName") String firstName);
2nd one JPA Query by method
List<User> deleteByLastname(String lastname);
When you go with query by method (2nd way) it will first do a get call
select * from user where last_name = :firstName
Then it will load it in a List
Then it will call delete id one by one
delete from user where id = 18
delete from user where id = 19
First fetch the list of object, then for loop to delete id one by one
But, the 1st option (custom query),
It's just a single query
It will delete wherever the value exists.
Since in 2nd option it is making multiple DB query, try to use the first option.
Go through this link too https://www.baeldung.com/spring-data-jpa-deleteby
If you take a look at the source code of Spring Data JPA, and particularly the PartTreeJpaQuery class, you will see that is tries to instantiate PartTree.
Inside that class the following regular expression
private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")
should indicate what is allowed and what's not.
Of course if you try to add such a method you will actually see that is does not work and you get the full stacktrace.
I should note that I was using looking at version 1.5.0.RELEASE of Spring Data JPA
If you will use pre defined delete methods as directly provided by spring JPA then below two queries will be execute by the framework.
First collect data(like id and other column) using by execute select query with delete query where clause.
then after getting resultSet of first query, second delete queries will be execute for all id(one by one)
Note : This is not optimized way for your application because many queries will be execute for single MYSQL delete query.
This is another optimized way for delete query code because only one delete query will execute by using below customized methods.
#NamedNativeQueries({
#NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
,
#NamedNativeQuery(name = "Abc.getByMaxId",
query = "SELECT max(id) from abc")
})
#Entity
public class Abc implements Serializable {
}
#Repository
public interface AbcRepository extends CrudRepository {
int getByMaxId();
#Transactional
#Modifying
void deleteByCreatedTimeBetween(String startDate, String endDate);
}
It works just
import org.springframework.transaction.annotation.Transactional;
#Transactional
Long removeAddressByCity(String city);
Yes , deleteBy method is supported
To use it you need to annotate method with #Transactional
here follows my 2 cents. You can also use native queries, like:
#Modifying
#Query(value="delete from rreo r where r.cod_ibge = ?1 and r.exercicio= ?2", nativeQuery = true)
void deleteByParameters(Integer codIbge, Integer exercicio);
#Query(value = "delete from addresses u where u.ADDRESS_ID LIKE %:addressId%", nativeQuery = true)
void deleteAddressByAddressId(#Param("addressId") String addressId);

Resources