Jpa Spring Boot error -> cannot convert object to type boolean - spring

Hello the actual error is :
Exception in thread "main" org.springframework.core.convert.ConversionFailedException:
Failed to convert from type [java.lang.Object[]] to type [boolean] for value '{2, ramesh, pass, 12345, ramu}';
nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Integer] to type [boolean]
Here i tried to create a method to find users by id , but when i tried to put the values into boolean type it gives above error
#Query("select case when count(s)>0 then true else false end from user_dao s where s.id =:id ")
#Query(value = "select * from user_dao where id =:id ", nativeQuery = true)
boolean isStudentExistsById(#Param("id") Integer id);
in main method -> this should print true or false.
System.out.println(userRepo.isStudentExistsById(2));
in constructor of bean
UserDao(int id, String name, String phone, String user_name, String
password) {
this.id = id;
this.name = name;
this.phone = phone;
this.user_name = user_name;
this.password = password;
}

Easiest way - use method of CrudRepository (your repository inherited it usually):
boolean existsById(Integer id)
For other options see Spring Data JPA and Exists query

Related

JdbcBatchItemWriter - setSql - How to fix timestamp type mismatch

I am using JdbcBatchItemWriter in my Springboot application to import data from a CSV file into an Oracle DB, but I’m not able to import in timestamps. I get the error Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime
I understand the error – I just don’t understand how to fix it. Is there a way to mark the insert statement so that it reads it as a timestamp?
I did try:
INSERT INTO HB357(START_DATE) VALUES (TO_DATE(:START_DATE, YYYY-MM-DD, HH:mm:SS)
And I tried
TO_TIMESTAMP(:START_DATE, YYYY-MM-DD HH24:mm:SS)
but it didn't work
I also have tried changing the entity type to String instead of LocalDataTime, but this results in not a valid month error.
So I then tried altering the session before the insert (with the entity type still as string):
itemWriter.setSql("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'");
And then running the insert state but also got the not a valid month error
ENTITY:
#Entity
#NamedQuery(name ="HB357.getListOfResponseIds", query = "SELECT RESPONSE_ID from HB357")
public class HB357 {
#Id
private String RESPONSE_ID;
#JsonFormat(pattern="yyyy-MM-dd#HH:mm:ss")
private LocalDateTime START_DATE;
private String STOVE_OPTION;
private String FIRST_NAME;
private String LAST_NAME;
private String ADDRESS;
private String CITY;
private String ZIPCODE;
private String COUNTY;
//Getters and Setters left out for brevity
Relevant Insert Function
#Bean
public JdbcBatchItemWriter<HB357> writer() {
JdbcBatchItemWriter<HB357> itemWriter = new JdbcBatchItemWriter<>();
itemWriter.setDataSource(appProperties.dataSource());
itemWriter.setSql("INSERT INTO HB357 (" +
"START_DATE, RESPONSE_ID, STOVE_OPTION, FIRST_NAME,LAST_NAME,ADDRESS,CITY,ZIPCODE,COUNTY,PHONE_NUMBER,EMAIL," +
"STOVE_LOCATION,EXEMPTIONS,AGI,INCENTIVE,INCENTIVE_AMT) " +
"VALUES (:START_DATE, :RESPONSE_ID, :STOVE_OPTION, :FIRST_NAME, :LAST_NAME, :ADDRESS, :CITY," +
":ZIPCODE, :COUNTY, :PHONE_NUMBER, :EMAIL, :STOVE_LOCATION, :EXEMPTIONS, :AGI," +
":INCENTIVE, :INCENTIVE_AMT)" );
itemWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
return itemWriter;
}
create class eg . public class HB357ParameterSourceProvider implements ItemSqlParameterSourceProvider and implement/do transformation for datatype inside it.
eg MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("start time", <>")
return param
pojo -> use instant start time conver date into timestamp(in case of sql server) and set
ItemSqlParameterSourceProvider valueSetter = new HB357ParameterSourceProvider ()
writer.setItemSqlParameterSourceProvider(valueSetter)

Getting single result of type int in hibernate

I have a controller that communicates with my service to get the id of the logged in user. I first get the username using principal object
#ResponseBody
#RequestMapping(value = "/lid",method = RequestMethod.GET)
public Integer lid(Principal p) {
String name = p.getName();
Integer gotid = personService.getDbId(name);
return gotid;
}
then call the service passing the username to the dao
public Integer getDbId(String name){
Session currentSession = sessionFactory.getCurrentSession();
#SuppressWarnings("rawtypes")
Query theQuery = currentSession.createQuery("select id from app_user where sso_id=:name");
//set multiple parameters from the user
//theQuery.setParameter("city", city);
theQuery.setParameter("sso_id", name);
//Get the int or the big int
//Get results into list object : List list = query.list();
int theid = (int)theQuery.getSingleResult();
//uniqueResult
return theid;
//org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: from near line 1, column 8 [select from app_user where sso_id=:name]
}
However, i get this error
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: app_user is not
mapped [select id from app_user where sso_id=:name]
How can i fix it to give me the one result that i want?.
You are trying to execute pure SQL but hibernate expects HQL. So it tries to find an Entity with app_user name but fails - there is no such class.
Try instead
Query theQuery = currentSession.createSQLQuery("...");
Try with this
Query theQuery = currentSession.createQuery("select id from AppUser where ssoId=:name");
AppUser might be your class name and ssoId is field name.
use your Domain class name and domain field names whatever it is because query requires HQL.

How to insert into db in spring-data?

I want to make a request that inserts data into my database. The table has 4 columns: ID_DOCUMENT (PK), ID_TASK, DESCRIPTION, FILEPATH
Entity
...
#Column(name = "ID_TASK")
private Long idTask;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "FILEPATH")
private String filepath;
...
Repository
#Modifying
#Query("insert into TaskDocumentEntity c (c.idTask, c.description, c.filepath) values (:id,:description,:filepath)")
public void insertDocumentByTaskId(#Param("id") Long id,#Param("description") String description,#Param("filepath") String filepath);
Controller
#RequestMapping(value = "/services/tasks/addDocument", method = RequestMethod.POST)
#ResponseBody
public void set(#RequestParam("idTask") Long idTask,#RequestParam("description") String description,#RequestParam("filepath") String filepath){
//TaskDocumentEntity document = new TaskDocumentEntity();
taskDocumentRepository.insertDocumentByTaskId(idTask,descriere,filepath);
}
When I run my test, I get this error:
Caused by: org.hibernate.hql.ast.QuerySyntaxException: expecting OPEN, found 'c' near line 1, column 32 [insert into TaskDocumentEntity c (c.idTask, c.descriere, c.filepath) values (:id,:descriere,:filepath)]
I tried to remove the alias c, and still doesn`t work.
Spring data provides out of the box save method used for insertion to database - no need to use #Query. Take a look at core concepts of springData (http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.core-concepts)
thus in your controller just create object TaskDocumentEntity and pass it to repository
#RequestMapping(value = "/services/tasks/addDocument", method = RequestMethod.POST)
#ResponseBody
public void set(#RequestParam("idTask") Long idTask,#RequestParam("description") String description,#RequestParam("filepath") String filepath){
// assign parameters to taskDocumentEntity by constructor args or setters
TaskDocumentEntity document = new TaskDocumentEntity(idTask,descriere,filepath);
taskDocumentRepository.save(document);
}
There is a way to do this but it depends on the db you're using. Below worked for me in Oracle (using Dual table):
#Repository
public interface DualRepository extends JpaRepository<Dual,Long> {
#Modifying
#Query("insert into Person (id,name,age) select :id,:name,:age from Dual")
public int modifyingQueryInsertPerson(#Param("id")Long id, #Param("name")String name, #Param("age")Integer age);
}
So in your case, it would be (if Oracle):
#Modifying
#Query("insert into TaskDocumentEntity (idTask,description,filepath) select :idTask,:description,:filepath from Dual")
public void insertDocumentByTaskId(#Param("idTask") Long id,#Param("description") String description,#Param("filepath") String filepath)
I'm not sure which db you're using, here's a link which shows at the bottom which db's support select stmts without a from clause : http://modern-sql.com/use-case/select-without-from

How to use JpaRepository operations (findOne) when having a native query with union all statment

I need to use JpaRepository with a query that has an union statement inside. Is it possible? This is my current implementation and the error I get so far:
Entity:
#Entity
public class PaymentDetails {
#Id
#Column
private String id;
#Enumerated(EnumType.STRING)
#Column(name = "rowtype")
private PaymentType paymentType;
#Embedded
private CardDetails cardDetails;
#Embedded
private BankAccountDetails bankAccountDetails;
Interface and query:
public interface PaymentsRepositoryManagerPayment1 extends JpaRepository<PaymentDetails,String> {
#Query(value = "select id,'CARD' as rowtype, cardnumber, cardtype, nameoncard, expirydate, startdate, securitycode, semafonecr, issuenumber, "
+ "null accountnumber, null accountholdername, null sortcode, null bic, null iban, null currency from pcs.BsbTempCardDetails "
+ "where id = :id union all select id, 'BANK' as rowtype, null cardnumber, null cardtype, null nameoncard, null expirydate, null startdate, "
+ "null securitycode, null semafonecr, null issuenumber, accountnumber, accountholdername, sortcode, bic, iban, currency "
+ "from pcs.BsbTempBankAccountDetails where id = :id", nativeQuery = true) <br>
List< PaymentDetails > findPaymentDetails(#Param("id") String id);
Call:
#Autowired private PaymentsRepositoryManagerPayment1 paymentsRepositoryManagerPayment1;
#Transactional(value = "paymentsRepositoryTransactionManager")
public PaymentDetails retrievePaymentDetailsById1(String id) {
return paymentsRepositoryManagerPayment1.findOne(id);
}
ERROR:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not load an entity: [com.bskyb.repository.payments.model.PaymentDetails#cardId]; SQL [select paymentdet0_.id as id2_0_, paymentdet0_.accountholdername as accounth2_2_0_, paymentdet0_.accountnumber as accountn3_2_0_, paymentdet0_.bic as bic2_0_, paymentdet0_.currency as currency2_0_, paymentdet0_.iban as iban2_0_, paymentdet0_.sortcode as sortcode2_0_, paymentdet0_.cardnumber as cardnumber2_0_, paymentdet0_.cardtype as cardtype2_0_, paymentdet0_.expirydate as expirydate2_0_, paymentdet0_.issuenumber as issuenu11_2_0_, paymentdet0_.nameoncard as nameoncard2_0_, paymentdet0_.securitycode as securit13_2_0_, paymentdet0_.startdate as startdate2_0_, paymentdet0_.rowtype as rowtype2_0_ from PaymentDetails paymentdet0_ where paymentdet0_.id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not load an entity: [com.bskyb.repository.payments.model.PaymentDetails#cardId]
java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
All of what you showed doesn't seem to be too related to the exception you see:
The exception complaints about a table not being available. Make sure PaymentDetails exists when you issue the query (this is probably the reason you see the exception).
You call findOne(…). Thus the query declaration on findPaymentDetails(…) doesn't play into the use case at all.

Spring data JPA query with parameter properties

What is the simplest way of declaring a Spring data JPA query that uses properties of an input parameter as query parameters?
For example, suppose I have an entity class:
public class Person {
#Id
private long id;
#Column
private String forename;
#Column
private String surname;
}
and another class:
public class Name {
private String forename;
private String surname;
[constructor and getters]
}
... then I would like to write a Spring data repository as follows:
public interface PersonRepository extends CrudRepository<Person, Long> {
#Query("select p from Person p where p.forename = ?1.forename and p.surname = ?1.surname")
findByName(Name name);
}
... but Spring data / JPA doesn't like me specifying property names on the ?1 parameter.
What is the neatest alternative?
This link will help you: Spring Data JPA M1 with SpEL expressions supported. The similar example would be:
#Query("select u from User u where u.firstname = :#{#customer.firstname}")
List<User> findUsersByCustomersFirstname(#Param("customer") Customer customer);
https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
Define the query method with signatures as follows.
#Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(#Param("surname") String lastname,
#Param("forename") String firstname);
}
For further details, check the Spring Data JPA reference
What you want is not possible. You have to create two parameters, and bind them separately:
select p from Person p where p.forename = :forename and p.surname = :surname
...
query.setParameter("forename", name.getForename());
query.setParameter("surname", name.getSurname());
You could also solve it with an interface default method:
#Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(#Param("surname") String lastname,
#Param("forename") String firstname);
default User findByName(Name name) {
return findByForenameAndSurname(name.getLastname(), name.getFirstname());
}
Of course you'd still have the actual repository function publicly visible...
You can try something like this:
public interface PersonRepository extends CrudRepository<Person, Long> {
#Query("select p from Person AS p"
+ " ,Name AS n"
+ " where p.forename = n.forename "
+ " and p.surname = n.surname"
+ " and n = :name")
Set<Person>findByName(#Param("name") Name name);
}
if we are using JpaRepository then it will internally created the queries.
Sample
findByLastnameAndFirstname(String lastname,String firstname)
findByLastnameOrFirstname(String lastname,String firstname)
findByStartDateBetween(Date date1,Date2)
findById(int id)
Note
if suppose we need complex queries then we need to write manual queries like
#Query("SELECT salesOrder FROM SalesOrder salesOrder WHERE salesOrder.clientId=:clientId AND salesOrder.driver_username=:driver_username AND salesOrder.date>=:fdate AND salesOrder.date<=:tdate ")
#Transactional(readOnly=true)
List<SalesOrder> findAllSalesByDriver(#Param("clientId")Integer clientId, #Param("driver_username")String driver_username, #Param("fdate") Date fDate, #Param("tdate") Date tdate);
The simplicity of Spring Data JPA is that it tries to interpret from the name of the function in repository without specifying any additional #Query or #Param annotations.
If you are supplying the complete name, try to break it down as firstname and lastname and then use something like this -
HotelEntity findByName(String name);
My HotelEntity does contain the field name so JPA tries to interpret on its own to infer the name of the field I am trying to query on and create a subsequent query internally.
Some more evidence from JPA documentation -
Further details - here
Are you working with a #Service too? Because if you are, then you can #Autowired your PersonRepository to the #Service and then in the service just invoke the Name class and use the form that #CuriosMind... proposed:
#Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(#Param("surname") String lastname,
#Param("forename") String firstname);
}
and when invoking the method from the repository in the service, you can then pass those parameters.
for using this, you can create a Repository for example this one:
Member findByEmail(String email);
List<Member> findByDate(Date date);
// custom query example and return a member
#Query("select m from Member m where m.username = :username and m.password=:password")
Member findByUsernameAndPassword(#Param("username") String username, #Param("password") String password);
#Autowired
private EntityManager entityManager;
#RequestMapping("/authors/{fname}/{lname}")
public List actionAutherMulti(#PathVariable("fname") String fname, #PathVariable("lname") String lname) {
return entityManager.createQuery("select A from Auther A WHERE A.firstName = ?1 AND A.lastName=?2")
.setParameter(1, fname)
.setParameter(2, lname)
.getResultList();
}

Resources