I have a Spring Boot connected with Oracle Database application. The same version of the application works fine with MySQL, but when I try to do some requests to Oracle Database it throws error:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
"status":500,"error":"Internal Server
Error","trace":"org.springframework.dao.InvalidDataAccessResourceUsageException:
could not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet\r\n\tat
org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:281)\r\n\tat
org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)\r\n\tat
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)\r\n\tat
org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n\tat
org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n\tat
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154)
at com.example.pawel.expense.controller.ExpenseController.createExpense(ExpenseController.java:67) ~[classes/:na]
ECT...
So here is my controller method for this function:
#PostMapping("/expense")
ResponseEntity<Expense> createExpense(#Valid #RequestBody Expense expense) throws URISyntaxException {
Expense result = expenseRepository.save(expense);
return ResponseEntity.created(new URI("/api/expense/" + result.getId())).body(result);
}
And my Expense model
#NoArgsConstructor
#Data
#Table(name="expense")
#Entity
public class Expense {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private Instant date;
private double amount;
private String description;
#ManyToOne
private Category category;
#ManyToOne
private User user;
// Getters and setters
Here is my application.properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
spring.jpa.properties.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show-sql=true
spring.datasource.url=jdbc:oracle:thin:#localhost:1521:XE
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.username=system
spring.datasource.password=root
spring.datasource.initialization-mode=always
spring.datasource.validationQuery=SELECT 1
logging.level.org.hibernate.SQL=DEBUG
spring.server.compression.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
spring.jpa.properties.hibernate.format_sql=true
You should add Hibernate Dialect to your application.properties like so
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
Or create a Bean for Oracle datasource. Follow this guide for further information
Configuring Spring Boot for Oracle
Related
I am working on a spring boot app where I am using JPA for all data transactions and I came across this error while using OneToMany relationship.
Here are both my models:
user.java
#Entity
public class user {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private String role;
#ManyToOne(cascade=CascadeType.ALL)
private file f;
#JsonIgnore
#OneToMany(targetEntity=job.class,cascade=CascadeType.ALL)
private List<job> applied;
//getters ,setters and constuctors.
}
job.java
#Entity
public class job {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String role;
private String company;
private String salary;
private String description;
private String level;
private Date expiry;
private String skills;
private String location;
#JsonIgnore
#OneToMany(targetEntity=user.class,cascade=CascadeType.ALL)
private List<user> candidates;
//getters setters and constructor
}
here's the method that triggers the error:
public String applyToJob(Integer userId,Integer jobId)
{
job jobToApply= jobRepo.getOne(jobId);
user applier=userRepo.getById(userId);
List<job> jobs=applier.getApplied();
jobs.add(jobToApply);
applier.setApplied(jobs);
userRepo.save(applier);
List<user> candidates=jobToApply.getCandidates();
System.out.println(candidates);
candidates.add(userRepo.getOne(userId));
System.out.println(candidates);
jobToApply.setCandidates(candidates);
jobRepo.save(jobToApply);
return "Job Apply Success";
}
Now that I want to add data inside job's candidates field I get the below error:
2021-10-07 17:17:37.542 WARN 21696 --- [nio-8090-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2021-10-07 17:17:37.543 ERROR 21696 --- [nio-8090-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry '2' for key 'job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f'
2021-10-07 17:17:37.543 INFO 21696 --- [nio-8090-exec-4] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2021-10-07 17:17:37.564 ERROR 21696 --- [nio-8090-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '2' for key 'job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java
Seems like you are adding a candidate to the job entity, which is already previously mapped to that particular job.
Please thoroughly check your entries in the DB and try to find out if there is any candidate that is being added multiple times to the same job, preferably with id as 2.
Let me know if you face any further difficulties!
Given the following db structure:
And having the following mapping for this structure:
#Entity
#Table(name = "a")
class A {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private int aId;
#Column(name = "title")
private String title;
#Formula("(SELECT COUNT(*) FROM b WHERE b.a_id = aId)")
private Integer count;
}
My aim is to get the count of all references to A from B (where aId in the query is the value of the current entity).
But I get following Error:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
java.sql.SQLException: Unknown column 'a0_.aId' in 'where clause'
As Simon mentioned you need to use the name of the column, not the attribute name. In your example above this would be:
#Formula("(SELECT COUNT(*) FROM b WHERE b.a_id = id)")
You have to use the name of the column not the attribute name:
#Formula("(SELECT COUNT(*) FROM b WHERE b.a_id = a_id)")
I have two tables: tbl_services & tbl_sub_services. one service can have multiple sub-services. I am developing REST API using spring boot and trying to post data in services & subservices table. I can post data in services table but getting issue while posting in sub-services table. It's one-to-Many bidirectional Mapping.
Here is an exception which I am getting in postman.
{
"timestamp": "2019-06-09T04:10:22.002+0000",
"status": 500,
"error": "Internal Server Error",
"message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"trace": "org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement\n\tat
.
.
.
.
'tbl_services_id' cannot be null\n\tat com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)\n\tat com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)\n\tat com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1094)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1042)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1345)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1027)\n\tat com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)\n\tat com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)\n\t... 94 more\n",
"path": "/api/subservices"
Here is structure of both tables :
Entity Classes :
Services.class
#Entity
#Table(name="tbl_services")
public class Service {
// define fields
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="tbl_services_id")
private int id;
#Column(name="service_name")
private String serviceName;
#Column(name="service_desc")
private String serviceDesc;
#Column(name="service_image")
private String serviceImage;
#OneToMany(mappedBy="service",
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
private List<SubService> subServices;
public List<SubService> getSubServices() {
return subServices;
}
public void setSubServices(List<SubService> subServices) {
this.subServices = subServices;
}
}
SubService.class
#Entity
#Table(name="tbl_sub_services")
public class SubService {
// define fields
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="tbl_sub_services_id")
private int id;
#ManyToOne(
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name="tbl_services_id")
#JsonIgnore
private Service service;
public Service getService() {
return service;
}
#Column(name="sub_service_name")
private String subServiceName;
#Column(name="sub_service_desc")
private String subServiceDesc;
#Column(name="sub_service_image")
private String subServiceImage;
I am trying to post data from postman then I am getting an exception. Here is data which I am posting from postman.
Here is SubServicesHibernateDAOImpl.class
#Override
public void saveSubService(SubService theSubService) {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
System.out.println("SubService object : "+theSubService);
currentSession.saveOrUpdate(theSubService);
}
EDIT :
Here is json payload I am receiving in saveSubService method :
[id=0, service=null, subServiceName=GST, subServiceDesc=GST is a subservice which currently having , subServiceImage=path-to-image]
You get:
could not execute statement; SQL [n/a]; constraint [null]
I see that you are passing the service in the request but I do not see you load it before the save of SubService:
#Override
public void saveSubService(SubService theSubService) {
Session currentSession = entityManager.unwrap(Session.class);
Service loadedService = currentSession.load(Service.class
, theSubService.getService.getId();
theSubService.setService(loadedService);
currentSession.saveOrUpdate(theSubService);
}
or try to simply merge as you have proper cascading already in place:
#Override
public void saveSubService(SubService theSubService) {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
System.out.println("SubService object : "+theSubService);
currentSession.merge(theSubService);
}
Also, I am not sure why you need to unwrap the session. EntityManager and its interface would be sufficient in this case.
Today i was trying to add Customer to database using Hibernate Annotation but i dont know why i am facing a reference Problem with a table !
Please read the Exception below
ERROR: Referential integrity constraint violation:
"FKOFMCQE0O4K2TFOXB308SKTMQ3: PUBLIC.CUSTOMER FOREIGN
KEY(CUS_BILLINGADDRESSID) REFERENCES
PUBLIC.CUSTOMERBILLINGADDRESS(CUS_BILLINGADDRESSID) ('CBA00001')"; SQL
statement:
update Customer set cus_emailid=?, cus_mobileno=?, cus_name=?, cus_billingaddressid=?, cus_cartid=?, cus_loginid=?,
cus_shippingaddressid=? where cus_id=? [23506-193]
Apr 01, 2017 7:09:57 PM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
INFO: HHH000010: On release of batch it still contained JDBC statements
Apr 01, 2017 7:09:57 PM org.hibernate.internal.ExceptionMapperStandardImpl
mapManagedFlushFailure
ERROR: HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not
execute statement]
Apr 01, 2017 7:09:57 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/TechNXT] threw exception [Request processing failed; nested
exception is javax.persistence.PersistenceException:
org.hibernate.exception.ConstraintViolationException: could not
execute statement] with root cause
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKOFMCQE0O4K2TFOXB308SKTMQ3: PUBLIC.CUSTOMER FOREIGN
KEY(CUS_BILLINGADDRESSID) REFERENCES
PUBLIC.CUSTOMERBILLINGADDRESS(CUS_BILLINGADDRESSID) ('CBA00001')"; SQL
statement:
update Customer set cus_emailid=?, cus_mobileno=?, cus_name=?, cus_billingaddressid=?, cus_cartid=?, cus_loginid=?,
cus_shippingaddressid=? where cus_id=? [23506-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:372)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:314)
at org.h2.table.Table.fireConstraints(Table.java:967)
at org.h2.table.Table.fireAfterRow(Table.java:985)
at org.h2.command.dml.Update.update(Update.java:151)
at org.h2.command.CommandContainer.update(CommandContainer.java:98)
at org.h2.command.Command.executeUpdate(Command.java:258)
at org.h2.server.TcpServerThread.process(TcpServerThread.java:344)
at org.h2.server.TcpServerThread.run(TcpServerThread.java:158)
at java.lang.Thread.run(Unknown Source)
Here is my Two model Tables
NOTE : i have generated getters and Setters but not posting so making as small as possible
1. Customer table which has a references of the other table
#Entity
public class Customer {
#Id
private String cus_id;
private String cus_name;
private String cus_emailid;
private String cus_mobileno;
#OneToOne(cascade=CascadeType.REFRESH)
#JoinColumn(name="cus_loginid")
private CustomerDetails customerdetails;
#OneToOne(cascade=CascadeType.REFRESH)
#JoinColumn(name="cus_billingaddressid")
private CustomerBillingAddress customerbillingaddress;
#OneToOne(cascade=CascadeType.REFRESH)
#JoinColumn(name="cus_shippingaddressid")
private CustomerShippingAddress customershippingaddress;
#OneToOne(cascade=CascadeType.REFRESH)
#JoinColumn(name="cus_cartid")
private CustomerCart customercart;
My Customer Billing Address Model
#Entity
public class CustomerBillingAddress {
#Id
private String cus_billingaddressid;
private String cus_houseno;
private String cus_street;
private String cus_area;
private String cus_city;
private String cus_state;
private String cus_country;
private String cus_pincode;
#OneToOne(mappedBy="customerbillingaddress")
private Customer customer;
Similarly Other Models
And Finally My DAO method which add the Customer to db
here is the code !
#Transactional
public String addCustomer(Customer customer) {
System.out.println("CustomerDao -TechNXT\n");
Session ses = sf.openSession();
customer.setCus_id(generateCustomerid());
customer.setCustomerbillingaddress(new CustomerBillingAddress());
customer.setCustomershippingaddress(new CustomerShippingAddress());
customer.setCustomercart(new CustomerCart());
customer.getCustomerdetails().setCus_loginid(generateCustomerLoginid());
customer.getCustomerbillingaddress().setCus_billingaddressid(generateCustomerBillingid());
customer.getCustomershippingaddress().setCus_shippingaddressid(generateCustomershippingid());
customer.getCustomercart().setCus_cartid(generateCustomerCartid());
customer.getCustomerdetails().setCus_isenabled(true);
customer.getCustomerdetails().setCus_role("ROLE_USER");
Transaction tr = ses.beginTransaction();
ses.save(customer);
tr.commit();
ses.close();
return customer.getCustomerdetails().getCus_loginid();
}
Well i have being trying stuffs since 3hrs but failed to get a solution of it !!
Sorry for taking your precious time.
and Thanking you in advance for helping me !
can you mark the #Table annontation on your class
like
#Table(name ="Customer")
I have my entity called Post which has Id as a primary key.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id", unique = true, nullable = false)
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
In above code you may see GenerationType.IDENTITY which I would assume is responsible for generating a new ID in case of creation of a new Post.
However, when I make a HTTP POST with this JSON:
{"id":0,"title":"test","viewCount":0,"body":"test","tags":"","answerCount":0,"commentCount":0,"postTypeId":1,"favoriteCount":0,"creationDate":"Nov 25, 2015 11:43:22 AM","acceptedAnswerId":0,"lastEditorUserId":0,"score":0}
I am getting this error:
SEVERE: Servlet.service() for servlet [rest] in context with path [/StackExchange] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement] with root cause
java.sql.SQLException: Field 'Id' doesn't have a default value
I haven't set AI though, maybe that is the cause. But I am unable to alter the table. The data in the table are from SQL dumps and I can't alter it to set Id as AutoIncrement