This is my Data Repository file and i used native query to retrieve all data address(Locations) of Data. I called the function using Postman and I got null outputs of locations. This my first time of using Native query and its really impossible to solve these errors
DataRepository
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT dataAddress FROM Data")
List<DataProject> getDataAddress();
}
DataServiceImpl
public List<DataProject> getDataAddress() {
return dataRepository.getDataAddress();
}
DataService
List<DataProject> getDataAddress();
DataModel
#Entity
#Table(name = "CCCData")
public class Data {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long dataId;
#Column(name = "DATA_NAME")
private String dataName;
#Column(name ="DATA_ADDRESS")
private String dataAddress;
#Column(name = "DATA_DESC")
private String dataDesc;
#CreationTimestamp
private Date dateOfCreated;
#CreationTimestamp
private Date dateOfUpdated;
public long getDataId() {
return dataId;
}
public void setDataId(long dataId) {
this.dataId = dataId;
}
public String getDataName() {
return dataName;
}
public void setDataName(String dataName) {
this.dataName = dataName;
}
public String getDataAddress() {
return dataAddress;
}
public void setDataAddress(String dataAddress) {
this.dataAddress = dataAddress;
}
public String getDataDesc() {
return dataDesc;
}
public void setDataDesc(String dataDesc) {
this.dataDesc = dataDesc;
}
public Date getDateOfCreated() {
return dateOfCreated;
}
public void setDateOfCreated(Date dateOfCreated) {
this.dateOfCreated = dateOfCreated;
}
public Date getDateOfUpdated() {
return dateOfUpdated;
}
public void setDateOfUpdated(Date dateOfUpdated) {
this.dateOfUpdated = dateOfUpdated;
}
DataProjection
public interface DataProject {
String getDataAddress();
}
DataController
#GetMapping("/data/locations")
public List<DataProject> getDataAddress() {
return dataService.getDataAddress();
}
Postman Output
[
{
"dataAddress": null
},
{
"dataAddress": null
},
{
"dataAddress": null
},
{
"dataAddress": null
}
]
Spring won't return you only address using below query. It still return you DATA object
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT dataAddress FROM Data")
List<DataProject> getDataAddress();
}
for fetching only DataAddress you need to create a constructor inside Data model for DataAddress only
public Data(String dataAddress) {
this.dataAddress = dataAddress;
}
and your query will look like this:
public interface DataRepository extends JpaRepository<Data, Long> {
#Query(value = "SELECT new Data(dataAddress) FROM Data")
List<DataProject> getDataAddress();
}
Update 1 :
if you need this for other fields with same datatype and then above 'constructor' based method fails. There are some other alternatives:
You can fetch DATA object and use java stream map function to extract only 1 field. data.stream().map((data) -> data.getDataAddress()).collect(Collectors.toList())
You can use native SQL query to fetch only required fields.
#Query(value = "SELECT d.data_address FROM CCCData d", nativeQuery=true)
Related
I am using spring JPA to attempt to write records to a postGres DB. At the time of the commit, I am getting the following error:
Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "col_id" violates not-null constraint
Detail: Failing row contains (null, null, null, null, null)
I have the following repository interface:
public interface MyRepo extends JpaRepository <MyModel, String> {
}
, the following model class:
#Entity
#Validated
#Table(name = "my_table", schema="common")
public class MyModel {
#Id
#Column(name = "col_id")
private String id;
#Column(name = "second_col")
private String secCol;
#Column(name = "third_col")
private String thirdCol;
#Column(name = "fourth_col")
private String fourthCol;
#Column(name = "fifth_col")
private String fifthCol;
public MyModel() {
}
public MyModel(String id, String secCol, String thirdCol, String fourthCol, String fifthCol) {
this.id = id;
this.secCol = secCol;
this.thirdCol = thirdCol;
this.fourthCol = fourthCol;
this.fifthCol = fifthCol;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSecCol() {
return secCol;
}
public void setSecCol(String secCol) {
this.secCol = secCol;
}
public String getThirdCol() {
return thirdCol;
}
public void setThirdCol(String thirdCol) {
this.thirdCol = thirdCol;
}
public String getFourthCol() {
return fourthCol;
}
public void setFourthCol(String fourthCol) {
this.fourthCol = fourthCol;
}
public String getFifthCol() {
return fifthCol;
}
public void setFifthCol(String fifthCol) {
this.fifthCol = fifthCol;
}
}
, and the relevant part of the service class:
public MyModel myModel (MyModel myModel) {
MyModel mm = null;
try {
mm = myRepo.saveAndFlush(myModel);
} catch ( Exception e) {
e.printStackTrace();
}
return mm;
}
UPDATE:
I finally realized that my problem is due to a database trigger that auto-generates primary key against a complex business rule. Also, I assume I might need to use a custom save method rather than the default repo.saveAndFlush? I would be grateful for any ideas given new information. Thanks!
I reproduced the exact same code in a test project with Postgres and it worked well for me. You are absolutely correct that the values of the model class are not populated. You must share your controller also. It may really help me to help you if I can get a look where your service is being called from. Only that will help me to deduce why your model values are being passed as null in the service call.
I have a case where I need to execute an insert statement via createNativeQuery. I have an entity list I'm looping through in order to set the properties accordingly from another bean class, and then persist that data to the oracle database.
The problem I am facing is persisting the data that is part of the embeddedId (item, loc, weekstart, type, forecastId, insertTS). I need to persist that data for the new records to be inserted into the database. When I try to set the values from the POJO bean to my set method for the properties of my entity bean, nothing happens. Below is my code for setting the values of the properties from the POJO bean to my entity bean, along with my persistence method and the insert query being executed:
Validation class where validation occurs beforehand (missing to get the point) that includes the setting of my entity properties from the POJO bean:
List <InsertPromoData> insertPromos = new ArrayList<InsertPromoData>();
promo.forEach(record -> {
if (record.getErrorList().size() == 0) {
rowsSuccessful++;
Util.writeSuccessToFile(templateCd, successFile, record, successFields);
try {
InsertPromoData insertData = new InsertPromoData();
insertData.getId().setItem(record.getItem());
insertData.getId().setLoc(record.getLoc());
insertData.getId().setWeekStart(record.getWeek_Start_Date());
insertData.setNumberOfWeeks(record.getNumber_Of_Weeks());
insertData.getId().setType(record.getType());
insertData.getId().setForecastId(record.getForecast_ID());
insertData.setQty(record.getUnits());
insertPromos.add(insertData);
}
catch (Exception e) {
logger.error("Error with setting insertPromolist from promo list values and the error is " + e.getMessage());
}
}
else {
if (rowsFailure == 0) {
Util.writeHeaderToFile(templateCd, errorFile);
}
rowsFailure++;
Util.writeErrorToFile(templateCd, errorFile, record, record.getErrorList());
}
});
errorFile.close();
successFile.close();
OracleImpl.insertPromoData(insertPromos);
POJO bean (promo is the variable representing this list of beans in validation class above):
public class PromoBean extends ErrorListBean
{
public String Item;
public String Loc;
public String Week_Start_Date;
public String Units;
public String Forecast_ID;
public String Type;
public String Number_Of_Weeks;
public String getItem() {
return Item;
}
public void setItem(String item) {
Item = item;
}
public String getLoc() {
return Loc;
}
public void setLoc(String loc) {
Loc = loc;
}
public String getWeek_Start_Date() {
return Week_Start_Date;
}
public void setWeek_Start_Date(String week_Start_Date) {
Week_Start_Date = week_Start_Date;
}
public String getNumber_Of_Weeks() {
return Number_Of_Weeks;
}
public void setNumber_Of_Weeks(String number_Of_Weeks) {
Number_Of_Weeks = number_Of_Weeks;
}
public String getType() {
return Type;
}
public void setType(String type) {
Type = type;
}
public String getForecast_ID() {
return Forecast_ID;
}
public void setForecast_ID(String forecast_ID) {
Forecast_ID = forecast_ID;
}
public String getUnits() {
return Units;
}
public void setUnits(String units) {
Units = units;
}
}
Embeddable class representing the composite primary key of the table:
#Embeddable
public class PromoID implements Serializable {
#Column(name = "ITEM")
private String item;
#Column(name = "LOC")
private String loc;
#Column(name = "WK_START")
private String weekStart;
#Column(name = "TYPE")
private String type;
#Column(name = "FCSTID")
private String forecastId;
#Column(name = "U_TIMESTAMP")
private String insertTS;
public PromoID() {
}
public PromoID (String item, String loc, String weekStart, String type, String forecastId, String insertTS) {
this.item = item;
this.loc = loc;
this.weekStart = weekStart;
this.type = type;
this.forecastId = forecastId;
this.insertTS = insertTS;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public String getWeekStart() {
return weekStart;
}
public void setWeekStart(String weekStart) {
this.weekStart = weekStart;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getForecastId() {
return forecastId;
}
public void setForecastId(String forecastId) {
this.forecastId = forecastId;
}
public String getInsertTS() {
return insertTS;
}
public void setInsertTS(String insertTS) {
this.insertTS = insertTS;
}
//hashcode and equals methods
Persistence Bean:
#Entity
#Table(name = "U_USER_PROMO")
public class InsertPromoData {
#EmbeddedId
private PromoID id;
#Column(name="NUMBER_OF_WEEKS")
String numberOfWeeks;
#Column(name="QTY")
String qty;
#Id
#AttributeOverrides(
{
#AttributeOverride(name = "item",column = #Column(name="ITEM")),
#AttributeOverride(name = "loc", column = #Column(name="LOC")),
#AttributeOverride(name = "weekStart", column = #Column(name="WK_START")),
#AttributeOverride(name = "type", column = #Column(name="TYPE")),
#AttributeOverride(name = "forecastId", column = #Column(name="FCSTID"))
}
)
public PromoID getId() {
return id;
}
public void setId(PromoID id) {
this.id = id;
}
public String getNumberOfWeeks() {
return numberOfWeeks;
}
public void setNumberOfWeeks(String numberOfWeeks) {
this.numberOfWeeks = numberOfWeeks;
}
public String getQty() {
return qty;
}
public void setQty(String qty) {
this.qty = qty;
}
}
DAO class method to execute the update (entitymanagerfactory emf already initialized):
public static void insertPromoData(List<InsertPromoData> insertData) {
logger.debug("Execution of method insertPromoData in Dao started");
System.out.println("Size of the insertData list is " + insertData.size());
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
System.out.println("Beginning transaction for insertPromoData");
Query query = em.createNativeQuery(env.getProperty("insertPromoUploadData"));
for (InsertPromoData promoData : insertData) {
query.setParameter("item", promoData.getId().getItem());
query.setParameter("location", promoData.getId().getLoc());
query.setParameter("wkStart", promoData.getId().getWeekStart());
query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());
query.setParameter("type", promoData.getId().getType());
query.setParameter("fcstId", promoData.getId().getForecastId());
query.setParameter("quantity", promoData.getQty());
query.executeUpdate();
}
em.getTransaction().commit();
}
catch(Exception e) {
logger.error("Exception in beginning transaction");
e.printStackTrace();
}
finally {
em.clear();
em.close();
}
logger.debug("Execution of method insertPromoData in Dao ended");
}
Query in properties file:
insertPromoUploadData = INSERT INTO {h-schema}U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY, U_TIMESTAMP) VALUES (:item, :location, TO_DATE(:wkStart,'MM DD YYYY'), :numberOfWeeks, :type, :fcstId, :quantity, SYSDATE)
My list size from my DAO class is returning as 0 once I begin the transaction and not sure why it is empty. Is there a reason that it is empty? I'm trying to persist each of the fields to the database (including the composite key fields) via insert query. Any help appreciated.
After looking into this for hours, I finally came to the conclusion that the simplest way to executeUpdate() without running into issues due to my current #EmbeddedId/#Embeddable logic was to change it to use #IdClass for my composite PK class, and annotate the fields from the PK in my entity with #Id. This allowed my data to be persisted to the database. Another slight difference was adding the insertTS in my entity class and annotating with #Id and generating getters/setters. This was necessary for JPA to recognize all the properties being referenced that I am wanting to persist, though I am persisting insertTS using SYSDATE function from the oracle DB instead of utilizing the get/set methods and setting to the current time from the java side.
I am sure there is a way to use #EmbeddedId/#Embeddable logic and be able to persist the fields that are part of the EmbeddedId, however, this I found to be a more simplistic way of doing it without further complexity in the code.
When I am trying to implement the JPQL query, I am getting the following error,
{
"message": "could not execute query; SQL [select alerts0_.nalert_id as nalert_i1_0_, alerts0_.bis_active as bis_acti2_0_, alerts0_.dalert_date as dalert_d3_0_, alerts0_.ndept_to as ndept_to4_0_, alerts0_.ninst_to as ninst_to5_0_, alerts0_.nreceiver_id as nreceive6_0_, alerts0_.nsender_id as nsender_7_0_, alerts0_.nsubdept_to as nsubdept8_0_, alerts0_.salert_action_data as salert_a9_0_, alerts0_.salert_desc as salert_10_0_, alerts0_.salert_subject as salert_11_0_, alerts0_.salert_type as salert_12_0_ from alerts alerts0_ where alerts0_.ninst_to=?]; nested exception is org.hibernate.exception.DataException: could not execute query",
"error": "Internal Server Error",
"path": "/spacestudy/rockefeller/control/alerts/getAlertDetails"
}
And my repository query is like the following,
#Query("SELECT a FROM Alerts a")
public List<Alerts> findByAlertType();
When I hard-coded Query like #Query("SELECT a FROM Alerts a WHERE a.nreceiverId = 649"), then also getting the same error.
And I am calling this query in my service like the following:
alert= alertsRepositoryObj.findByAlertType();
And my model class Alerts.java like the following:
#Entity
#Table(name="alerts")
public class Alerts implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "alerts_seq_generator")
#SequenceGenerator(name = "alerts_seq_generator", sequenceName = "alerts_seq",allocationSize=1)
#Column(name="nalert_id",columnDefinition="serial")
public Integer nalertId;
#Column(name="salert_desc")
public String salertDesc;
#NotNull
#Column(name="nsender_id")
public Integer nsenderId;
#Column(name="dalert_date")
public LocalDate dalertDate;
#Column(name="salert_subject")
public String salertSubject;
#Column(name="salert_action_data")
public String salertActionData;
#Column(name="salert_type")
public String salertType;
#Column(name="ninst_to")
public Integer ninstTo;
#Column(name="ndept_to")
public Integer nDeptTo;
#Column(name="nsubdept_to")
public Integer nsubdeptTo;
#Column(name="nreceiver_id")
public Integer nreceiverId;
#NotNull
#Column(name="bis_active")
public Boolean bisActive=true;
#ManyToOne(optional = true)
#JoinColumn(name = "salert_action_data", insertable = false, updatable = false)
public RoomTransfer roomTransfer;
public Integer getNalertId()
{
return nalertId;
}
public void setNalertId(Integer nalertId)
{
this.nalertId = nalertId;
}
public String getSalertDesc()
{
return salertDesc;
}
public void setSalertDesc(String salertDesc)
{
this.salertDesc = salertDesc;
}
public Integer getNsenderId()
{
return nsenderId;
}
public void setNsenderId(Integer nsenderId)
{
this.nsenderId = nsenderId;
}
public LocalDate getDalertDate()
{
return dalertDate;
}
public void setDalertDate(LocalDate dalertDate)
{
this.dalertDate = dalertDate;
}
public String getSalertSubject()
{
return salertSubject;
}
public void setSalertSubject(String salertSubject)
{
this.salertSubject = salertSubject;
}
public String getSalertActionData()
{
return salertActionData;
}
public void setSalertActionData(String salertActionData)
{
this.salertActionData = salertActionData;
}
public String getSalertType()
{
return salertType;
}
public void setSalertType(String salertType)
{
this.salertType = salertType;
}
public Integer getNinstTo()
{
return ninstTo;
}
public void setNinstTo(Integer ninstTo)
{
this.ninstTo = ninstTo;
}
public Integer getnDeptTo()
{
return nDeptTo;
}
public void setnDeptTo(Integer nDeptTo)
{
this.nDeptTo = nDeptTo;
}
public Integer getNsubdeptTo()
{
return nsubdeptTo;
}
public void setNsubdeptTo(Integer nsubdeptTo)
{
this.nsubdeptTo = nsubdeptTo;
}
public Integer getNreceiverId()
{
return nreceiverId;
}
public void setNreceiverId(Integer nreceiverId)
{
this.nreceiverId = nreceiverId;
}
public Boolean getBisActive()
{
return bisActive;
}
public void setBisActive(Boolean bisActive)
{
this.bisActive = bisActive;
}
public RoomTransfer getRoomTransfer()
{
return roomTransfer;
}
public void setRoomTransfer(RoomTransfer roomTransfer)
{
this.roomTransfer = roomTransfer;
}
public Alerts()
{
super();
}
}
Why this error happening? Since this is a simple JPQL query. How can I trouble shoot the exact error here?
I am using the graphql-java-annotations library for java to retrieve data from my spring backend.
<dependency>
<groupId>io.github.graphql-java</groupId>
<artifactId>graphql-java-annotations</artifactId>
<version>7.1</version>
</dependency>
When I call the query it always return null.
This is my Provider class:
GraphQLAnnotations graphqlAnnotations = new GraphQLAnnotations();
GraphQLSchema graphQLSchema = newSchema()
.query(graphqlAnnotations.object(QueryTest.class))
.build();
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
This is the query:
#GraphQLName("queryTest")
public class QueryTest {
#GraphQLField
public static Test byId(final DataFetchingEnvironment env, #GraphQLName("id") Long id) {
return new Test();
}
}
And finally the Test.class
#GraphQLName("Test")
public class Test {
private String id;
private String name;
public Test() {
this("0");
}
public Test(String id) {
this.setName("Name" + id);
this.setId(id);
}
#GraphQLField
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#GraphQLField
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
This is my call:
{
"query" : "query queryTest { byId(id: 2) { getId } }",
"operationName" : "queryTest"
}
And this is the result i get:
{
"data": {
"byId": null
}
}
I debugged into the graphql execution and found out that schema contains TestClass and Test. So type and query are known. With this configuration I don't have a fetcher or a resolver.
Found the solution:
I had to change my Provider class in order to create the schema correctly via the AnnotationsSchemaCreator Builder:
GraphQLSchema graphQLSchema = AnnotationsSchemaCreator.newAnnotationsSchema()
.query(QueryTest.class)
.typeFunction(new ZonedDateTimeFunction())
.build();
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
My entity class is here:
public class ClientDetails {
public ClientDetails() {
super();
// TODO Auto-generated constructor stub
}
#Id
#GeneratedValue
#Column(name="serialno")
public int serialno;
#Column(name="gstnum")
public int GSTnum;
#Column(name="bunk_name")
public String bunk_name;
#Column(name="mobile_num")
public int mobile_num;
#Column(name="password")
public String password;
public int getSerialno() {
return serialno;
}
public void setSerialno(int serialno) {
this.serialno = serialno;
}
public int getGSTnum() {
return GSTnum;
}
public void setGSTnum(int gSTnum) {
GSTnum = gSTnum;
}
public String getBunk_name() {
return bunk_name;
}
public void setBunk_name(String bunk_name) {
this.bunk_name = bunk_name;
}
public int getMobile_num() {
return mobile_num;
}
public void setMobile_num(int mobile_num) {
this.mobile_num = mobile_num;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
I want to select gstnum from my table based on my bunk_name.I don't want any native query like i did for gstnum in my jpa repository.
SELECT gstnum from pbm.client_details where bunk_name = 'yoga';
MY JPA REPOSITORY is
public interface ClientDetailsRepository extends JpaRepository<ClientDetails,Integer> {
public static final String gst_num = "SELECT * FROM pbm.client_details;";
//public static final String login_access = "SELECT * FROM clien_details WHERE gstnum pbm.client_details;";
#Query(value = gst_num, nativeQuery = true)
List<ClientDetails> getGstnum();
}
You could use the #Query but Spring Data would result not having too
#Query("SELECT GSTnum FROM ClientDetails where bunk_name = :callMeSomething")
List<ClientDetails> getGstnum(#Param("callMeSomething") String callMeSomething);
How a look here JPA Docs