i am trying to do a POC - using JpaRepository filter out the data by adding two conditions.
I have written a code like below
public interface TemplateRepository extends JpaRepository<Template, Long> {
List<Template> findByTemplateNameContains(String templateName);//This is Working Fine
List<Template> findByTemplateNameAndActiveFlagContains(String templateName, String activeFlag);// My POC
}
templateName column is a VARCHAR2 and activeFlag is a Char in the Oracle Database. I am trying to filter the data with both templatename
and activeFlag.
I pass the input object in SoapUI app (POST) request.
{
"netting":"karu_test",
"activeFlag": "Y"
}
but I get the below error
"Parameter value [%Y%] did not match expected type [java.lang.Character (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [%Y%] did not match expected type [java.lang.Character (n/a)]"
I understand this error like, the ACTIVE_FLAG column is CHAR(1) so type mismatch happend. But how to achieve the same functionality ?
More over .. how to use multiple table joins and condition in JpaRepository
I changed the type of activeFlag to Char still i get the same error.
Template class
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
#Entity
#Table(name="TEMPLATE_DEF")
#Getter
#Setter
public class Template {
#Column(name="TEMPLATE_ID")
#Id
private String nettingTemplateId;
#Column(name="TEMPLATE_NAME")
private String templateName;
#Column(name="LAST_UPDATE")
private Date lastUpdate;
#Column(name="UPDATE_USER_ID")
private Integer updUsrId;
#Column(name="ACTIVE_FLAG")
private char activeFlag;
#Column(name="VERSION")
private Integer Version;
#Column(name="CREATION_DATE")
private Date creationDate;
#Column(name="CREATE_USER_ID")
private Integer createUsrId;
}
Please try the below JPA Query
List<Template> findByTemplateNameContainingAndActiveFlagContaining(String templateName, Character activeFlag);
Your Active flag is a char so no point in putting containing for activeFlag rather do a exact match, change method signature to
List<Template> findByTemplateNameContainsAndActiveFlag(String templateName, char activeFlag);// My POC
I have tested it it will match name with like and activeFlag based on value of it
Related
I've a spring boot application which is supposed to call an oracle stored procedure but when I send a request it returns 200 Ok with no payload returned. here is my code on how I called the oracle stored procedure.
#application.properties file
server.port=3000
spring.datasource.url=jdbc:oracle:thin:#xxxxxxxxx
#thin is popular oracle driver, localhost is the host of the database, 1521 is the port of the database, and xe is the database name
spring.datasource.username=XXXXXX
spring.datasource.password=XXXXXX
spring.datasource.driver-class-name= oracle.jdbc.OracleDriver
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.properties.hibernate.proc.param_null_passing=true
#my repo class to call the stored procedure
package com.amsadmacc.amsadmaccadapter.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
#Data
#Entity
#NoArgsConstructor
#Builder
#AllArgsConstructor
#NamedStoredProcedureQuery(
name = "test_stored_proc_sp",
procedureName = "Test_stored_proc"
)
public class PathwaysJourney implements Serializable {
#Id
private long id;
private Integer pidm;
private String firstName;
private String lastName;
private Integer termCode;
private String termDescription;
private Integer applicationNumber;
private String applicationStatusCode;
private String applicationStatusDescription;
private String applicationProgram;
private String majorCode;
private String majorDescription;
private Date applicationDate;
private Integer daysFromApplication;
private String email;
private String mobileNumber;
}
#my controller
#PostMapping("/pathwaysjourney1")
#ResponseBody
public List getAllPathways1() {
spridenRepo.serverOut();
StoredProcedureQuery proc = this.em.createNamedStoredProcedureQuery("Test_stored_proc");
System.out.println("===>>> start exec");
//String output=serverOut();
//log.info("Output {}",output);
proc.execute();
System.out.println("===>>> end exec");
return proc.getResultList();
}
The above end point in the controller returns an empty string like [] in the response body, I've tested the stored procedure in oracle sql developer it returns data.
Any Idea what the problem is? ,some say it is the " set serveroutput on" command, it should be turned on every time a call is made from spring boot, if so, how do we run that command from spring boot whenever the call is made?
I have an error regarding deploying the backend trough docker on localhost 8080 .
When i run the website normally (started the postgres server from inteliji) it works properly.
When i try to deploy it trough docker i get the following error:
org.postgresql.util.PSQLException: ERROR: operator does not exist: uuid = bigint
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Position: 580
The next code is an example of class using UUID
package com.ds.assignment1.ds2021_30244_rusu_vlad_assignment_1.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.UUID;
#Entity
#Data
public class Account {
#Id
#GeneratedValue(generator = "uuid4")
#GenericGenerator(name = "uuid4", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
private String username;
private String password;
private String role;
}
The error shows that the database column is UUID whereas the JPA entity is bigint. I should mention that this may be or may not be about the ID field of this entity.
As #Adrian-klaver said you have to look at position 580 of the SQL query, which you can do by enabling hibernate query logs and looking at the last hibernate SQL query log.
I had a similar problem, spending three days to finally resolve it. My problem was due to having multiple attribute types being different than their database type. As I was migrating from Long id to UUID, it made me confuse figuring out what the cause for my error was.
I want to create a new table every day with the full date as table name if the day is new create table for the that day
I have seen that when I change #Table(name="") name to a new string it make a new table but I can't automate this work
#Entity
#Table(name="orders_25_10_2021")
public class game2data {
#Id
private int cid;
private String name;
private Integer address;
private Integer gender;
private String date;
private String Done;
In simple words, I want to pass the name of #Table(name="") as a variable with dynamic according to date.
You can achieve this custom naming strategy by extending SpringPhysicalNamingStrategy and overriding its toPhysicalTableName method :
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Configuration;
#Configuration
public class TableNamingStrategy extends SpringPhysicalNamingStrategy {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd_MM_YYYY");
public static final PhysicalNamingStrategyStandardImpl INSTANCE =
new PhysicalNamingStrategyStandardImpl();
#Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
if (!name.getText().equals("game2data"))
return name;
StringBuilder customName =
new StringBuilder("orders").append('_').append(DATE_FORMATTER.format(LocalDate.now()));
return new Identifier(customName.toString(), name.isQuoted());
}
}
and registering it in your application.properties:
spring.jpa.hibernate.naming.physical-strategy=com.stackoverflow.questions.TableNamingStrategy
and removing the #Table annotation from the game2data entity.
This method is limited by the fact table names are determined at application start-up.
As a proof of concept, here's a way to update the table name every day by extending StatementInspector. By using this, you won't be able to read old data. You'll also have to use custom implementations of the JpaRepository's methods to create the new table every day before you insert data in it.
iam using spring data jpa in my project
package com.mf.acrs.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#Data
#Entity(name= "mv_garage_asset_mapping")
public class GarageAssetMapping implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2535545189473989744L;
#Id
#Column(name="GARAGE_CODE")
private String garageCode;
#Column(name="GARAGE_NAME")
private String garageName;
#Column(name="GARAGE_ADDRESS")
private String garageAddress;
#Column(name="GARAGE_BRANCH")
private String garageBranch;
#Column(name="CONTRACT_NUMBER")
private String contractNumber;
}
this is my entity object
package com.mf.acrs.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.mf.acrs.model.GarageAssetMapping;
public interface GarageAssetMappingRepository extends JpaRepository<GarageAssetMapping, String> {
// #Query(name="select u.CONTRACT_NUMBER from mv_garage_asset_mapping u where u.GARAGE_CODE = ?1", nativeQuery = true) //**QUERY 1**
#Query("select u.contractNumber from mv_garage_asset_mapping u where u.garageCode = ?1") // **QUERY 2**
List<String> findByGarageCode(String garageCode);
}
this is my repository interface
when i use the QUERY 1 in my application the query fired by spring data jpa is
Hibernate: select garageasse0_.garage_code as garage_code1_2_, garageasse0_.contract_number as contract_number2_2_, garageasse0_.garage_address as garage_address3_2_, garageasse0_.garage_branch as garage_branch4_2_, garageasse0_.garage_name as garage_name5_2_ from mv_garage_asset_mapping garageasse0_ where garageasse0_.garage_code=?
but when i use QUERY 2 the query fired is
Hibernate: select garageasse0_.contract_number as col_0_0_ from mv_garage_asset_mapping garageasse0_ where garageasse0_.garage_code=?
QUERY 2 gives me desired result.
but my question is why spring data jpa fires a incorrect query in 1st case.
in QUERY 1 hibernate tries to pull all the data fields despite the fact i have explicitly written in query that i want to fetch only one field.
What mistake iam doing in this case?
The method defined in the controller which calls the method is below:
#PostMapping("/searchAssetsAjax")
#ResponseBody
public String searchAssetsAjax(#RequestBody SearchAssetData searchAssetData) throws IOException{
System.out.println("iam in the searchAssetsAjax "+searchAssetData);
System.out.println("iam in the searchAssetsAjax "+searchAssetData.toString());
// System.out.println("throwing exceptions" ); throw new IOException();
System.out.println("hitting the db "+searchAssetData.getGarageCode());
// List<String> contractNums = garageAssetMapRepository.findContractNumberByGarageCode(searchAssetData.getGarageCode());
List<String> contractNums = garageAssetMapRepository.findByGarageCode(searchAssetData.getGarageCode());
System.out.println("############contract num size is "+contractNums.size());
for(String contract: contractNums) {
System.out.println("contract nums are "+contract);
}
return "success";
}
While running spring boot with h2 database and JPA i am getting below error.
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:440) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
It is caused due to below one
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE TABLE EXCHANGE_VALUE (ID INTEGER NOT NULL, CONVERSION_MULTIPLE DECIMAL(19,2), FROM[*] VARCHAR(255), PORT INTEGER NOT NULL, TO VARCHAR(255), PRIMARY KEY (ID)) "; expected "identifier"; SQL statement:
create table exchange_value (id integer not null, conversion_multiple decimal(19,2), from varchar(255), port integer not null, to varchar(255), primary key (id)) [42001-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357) ~[h2-1.4.197.jar:1.4.197]
at org.h2.message.DbException.getSyntaxError(DbException.java:217) ~[h2-1.4.197.jar:1.4.197]
My hibernate class
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="Exchange_Value")
public class ExchangeValue {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String from;
private String to;
private BigDecimal conversionMultiple;
private int port;
public ExchangeValue() {
}
public ExchangeValue(String from, String to, BigDecimal conversionMultiple) {
super();
// this.id = id;
this.from = from;
this.to = to;
this.conversionMultiple = conversionMultiple;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
application.properties is below
spring.application.name=currency-exchange-service
server.port=8000
spring.jpa.hibernate.ddl-auto= create-drop
Just want to know as to what i am missing in the code tried adding spring.jpa.hibernate.ddl-auto= create-drop but it did not helped.
#shubh.. Your Entity Field names are matching with SQL reserved keywords,
So try to change the field names otherwise use name attribute with #Column Annotation (which gives alias names to the DATABASE)
#Column(name="valueFrom")
private String from;
#Column(name="valueTo")
private String to;
private BigDecimal conversionMultiple;
private int port;
Your Entity Field name from was matched with database reserved word from,
change the field name to another, or add a #Column annotation on that field.
Like:
...
#Column(name = "_from")
private String from;
...
I faced the same issue. I did the mistake in giving the schema name in mysql database.
In spring.properties -> (spring boot application)
spring.datasource.url=jdbc:mysql://localhost:3306/db_microservice
Here instead of "db_microservice" I Have given the name as "db-microservice". So don't use "-". And this solved my issue.
#ganesh045's response isnt actually true because hibernate's table creation query works like this: CREATE TABLE <your_table> 'password' for example to each of your attributes. Adding the `` to the attribute will make SQL read it NOT as reserved keyword. It also does the same when it queries for your select clauses inside JpaRepository. It will make a call such as this: SELECT 'attribute' FROM <your_table>. Your problem is most likely that you specified your schema name as kebab-case or anything which is not camelCase and snake_case. Also, with this approach you can have a table called User with attribute's username and password which actually also are MYSQL reserved keywords.
Adding to others observation, I got the same error when a column name contains hyphen.
Error
#Column(name = "COST-CENTER")
private String costCenter;
Fixed
#Column(name = "COST_CENTER")
private String costCenter;
in my problem, database name was 'user'. that's why was giving a error. I changed database name, bug fixed.