DataException: could not execute query - java

I get this error when I try to run start my application:
org.springframework.dao.DataIntegrityViolationException: could not execute query; SQL [SELECT * FROM testquestions ORDER by id DESC LIMIT 1]; nested exception is org.hibernate.exception.DataException: could not execute query
As seen in previous problems on StackOverflow, I tried to adjust the length of my data input in my sql file and I've set the length of my #Column to the same amount of characters. this didn't help.
this is my #Table class:
#Entity
#Getter
#Setter
#Table(name = "testquestions")
public class TestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "questiontitle", length = 2000)
private String questionTitle;
#Column(name = "info", length = 4096)
private String Info;
#Column(name = "solvetime")
private int solveTime;
#Column(name = "difficultylevel")
private DifficultyLevel difficultyLevel;
#Column(name = "questionimage")
private Image questionImage;
public TestQuestion(){
}
public TestQuestion(int id, String questionTitle, String info, DifficultyLevel difficultyLevel) {
this.id = id;
this.questionTitle = questionTitle;
Info = info;
this.difficultyLevel = difficultyLevel;
}
public String getInfo() {
return Info;
}
}
This is my # Query in my QuestionRepository:
#Query(value = "SELECT * FROM testquestions ORDER by id DESC LIMIT 1", nativeQuery = true)
TestQuestion fetchLastQuestion();
This is my database.sql file, it writes to a PostgreSQL data base:
TRUNCATE TABLE users CASCADE;
TRUNCATE TABLE testquestions CASCADE;
DROP TABLE users;
DROP TABLE testquestions;
CREATE TABLE users(
id int,
username varchar(255),
password varchar(255),
role varchar(255)
);
CREATE TABLE testquestions(
id int primary key ,
questiontitle varchar(2000),
info varchar(4096),
solvetime int,
difficultylevel varchar(255),
questionimage bytea
);
INSERT INTO users(id, username, password, role)
VALUES (0, 'user', 'u', 'user'),
(1, 'user','u','user');
INSERT INTO testquestions(id,questiontitle, info, solvetime, difficultylevel, questionimage)
VALUES (0, 'Multiple Databases', 'A company wants to use Spring Boot in a web application which should use JPA as a database abstraction. The unit tests should be run on an H2 database while the production should run on a MySQL database.
Select all the things that need to be done or that will be done automatically by Spring Boot.', 3, 'Easy',
''),
(1, 'Screen Orientation', 'Which of these methods are called when the screen changes orientation from portrait to landscape in Android?',
3, 'Easy',''),
(2, 'Merge Names', 'Implement the uniqueNames method. When passed two arrays of names, it will return an array containing the names that appear in either or both arrays. The returned array should have no duplicates.
For example, calling MergeNames.uniqueNames(new String[]{''Ava'', ''Emma'', ''Olivia''}, new String[]{''Olivia'', ''Sophia'', ''Emma''}) should return an array containing Ava, Emma, Olivia, and Sophia in any order.',
10, 'Easy',''),
(3, 'Date', 'Write a function that converts user entered date formatted as M/D/YYYY to a format required by an API (YYYYMMDD). The parameter "userDate" and the return value are strings.
For example, it should convert user entered date "12/31/2014" to "20141231" suitable for the API.', 10, 'Easy', ''),
(4, 'Inspector', 'Fix the bugs in the following HTML code.', 10, 'Easy',''),
(5, 'Train Composition', 'A TrainComposition is built by attaching and detaching wagons from the left and the right sides, efficiently with respect to time used.
For example, if we start by attaching wagon 7 from the left followed by attaching wagon 13, again from the left, we get a composition of two wagons (13 and 7 from left to right). Now the first wagon that can be detached from the right is 7 and the first that can be detached from the left is 13.
Implement a TrainComposition that models this problem.', 20, 'Hard', '');
Has anyone got an idea how to fix this error?
Thanks!
Tom

Related

ORA_02201 Sequence is not allowed here

hope you all doing well. I'm continuously getting "ORA_02201 - Sequence is not allowed here" SQL syntax error when I'm trying to post new entry to Database using JSON. I'm using Oracle Autonomous Database
In Oracle Database, folks use GenerationType.SEQUENCE strategy for ID (Primary Key) increment.
I've tried something beforehand, let me share with you. It seems root of the issue is that Sequence is not working with JSON, or not set up to be working. It gives "Sequence is not allowed here" when my JSON request doesn't have id, so when Sequence is supposed to work.
Note that, I have this app as MVC web application where I save entity into database through getting data from form input in jsp pages. It works flawlessly and generate ID correctly. Problem is with JSON I believe.
{
"firstName" : "Mark",
"lastName" : "Heiberg",
"email" : "heibergmark#dot.com"
}
I made request by specifying the Id in JSON which id exists in database, then it updated the entry. So I get assured that root of the cause is id generation, when it should make new id, it doesn't work. I couldn't find anything about JSON-Oracle DB relationship in Internet. I wanted to ask here, maybe you know can I or should I do something to enable support for Sequence generation type on the moment of JSON request. Thanks in advance.
#PostMapping("/customers")
Customer addCustomer(#RequestBody Customer customer){
customer.setId(0); //set id to 0 to force it to add customer to DB, instead of updating current.
customerService.saveCustomer(customer);
return customer;
}
This is Table Definition SQL: (I've built it using Oracle APEX environtment, don't mind that 9999999999999999, it's by default)
CREATE TABLE "CUSTOMER"
( "ID" NUMBER(3,0) GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE,
"FIRST_NAME" VARCHAR2(15) COLLATE "USING_NLS_COMP",
"LAST_NAME" VARCHAR2(15) COLLATE "USING_NLS_COMP",
"EMAIL" VARCHAR2(30) COLLATE "USING_NLS_COMP",
CONSTRAINT "CUSTOMER_PK" PRIMARY KEY ("ID")
USING INDEX ENABLE
) DEFAULT COLLATION "USING_NLS_COMP"
/
CREATE OR REPLACE EDITIONABLE TRIGGER "BI_CUSTOMER"
before insert on "CUSTOMER"
for each row
begin
if :NEW."ID" is null then
select "CUSTOMER_SEQ".nextval into :NEW."ID" from sys.dual;
end if;
end;
/
ALTER TRIGGER "BI_CUSTOMER" ENABLE
/
This is my Entity class where Database annotations is implemented:
package com.customer_tracker.entity;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#Entity
#Table(name = "CUSTOMER")
public class Customer {
public Customer() {
}
public Customer(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Customer_SEQ")
#SequenceGenerator(name = "Customer_SEQ", sequenceName = "CUSTOMER_SEQ", allocationSize = 1)
#Column(name = "ID")
private int id;
#NotNull(message = "This field is required!")
#Size(min = 3, max = 15, message = "Write something!")
#Column(name = "FIRST_NAME")
private String firstName;
#NotNull(message = "This field is required!")
#Size(min = 3, max = 15, message = "Write something!")
#Column(name = "LAST_NAME")
private String lastName;
#NotNull(message = "This field is required!")
#Size(min = 3, max = 30, message = "Write something!")
#Column(name = "EMAIL")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName.trim().replaceAll("\\s", "");
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName.trim().replaceAll("\\s", "");
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email.trim().replaceAll("\\s", "");
}
#Override
public String toString() {
return "id = " + id +
", firstName = " + firstName + ", lastName = " + lastName + ", email = " + email;
}
}
This is the code snippet where Hibernate going to save entry to Database:
package com.customer_tracker.dao;
import com.customer_tracker.entity.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public class CustomerList implements CustomerDAO{
#Autowired
private SessionFactory sessionFactory;
#Override
public void saveCustomer(Customer customer) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(customer);
}
}
... GET, PUT, DELETE methods work as desired, only POST doesn't work as database should generate id behind the scenes.
The problem is that you are using an identity column with the option generated always, but at the same time you are using a trigger to populate the column ID with a sequence. You can't do that, either you use a sequence and a trigger, or you use identity columns. If you are in Oracle 12c or higher, I strongly recommend you to use identity columns, unless some of the restrictions they inherit may affect the way your application behaves.
See this example
SQL> create table test_col ( c1 number generated always as identity start with 1 increment by 1 , c2 varchar2(1) ) ;
Table created.
SQL> insert into test_col ( c2 ) values ( 'A' ) ;
1 row created.
SQL> select * from test_col ;
C1 C
---------- -
1 A
SQL> insert into test_col ( c1,c2 ) values ( 2,'B' ) ;
insert into test_col ( c1,c2 ) values ( 2,'B' )
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column
You have to drop the trigger and the sequence as they are useless in this scenario. The error is surely raised when the trigger is fired. When you use identity columns, Oracle handles automatically for you the sequence and the insert.
The identity columns are subject to the following restrictions:
Each table has one and only one identity column.
The data type of the identity column must be a numeric data type. the user-defined data type is not allowed to use with the identity clause.
The identity column is not inherited by the CREATE TABLE AS SELECTstatement.
The identity column cannot have another DEFAULT constraint.
The encryption algorithm for encrypted identity columns can be inferred therefore you should use a strong encryption algorithm.
The inline constraint of the identity column must not conflict with the NOT NULL and NOT DEFERRABLE constraint stated by the identity clause.
generated always is one of the options for Identity Columns. Read more about that in the link below
Identity Columns
if you are using JPA you should have #Id and #GeneratedValue (with proper strategy) annotations over id field and it will be auto-generated.
Example: https://spring.io/guides/gs/accessing-data-jpa/

Cannot resolve column [name] in Java using Microsoft SQL Server and Javax.Persistence

One of my classes that convert table in SQL Server database to entities.
#Id
#Column(name = "[primary_key]")
private int id;
#Column(name = "[id Employee]")
private byte[] employeeId;
#Column(name = "[Period]")
private Date period;
#Column(name = "[Credit amount]")
private float creditAmount;
#Column(name = "[Type]")
private String type;
#Column(name = "[Weight 585]")
private float weight585;
and CrudRepo for it (partial):
#Query(value = "select sum([Weight 585]) from [ZOK per period] where ([Period] between ?1 and ?2) " +
"and ([id Employee] = ?3) and ([Type] = 'Gold')", nativeQuery = true)
Double getSumZokGold(Date start, Date end, byte[] employeeId);
All my column names are red and underlined with two errors:
Cannot resolve column '';
Unknown database function '';
I checked persistence and data already assigned - its most popular solution of this problem. I checked dialect - SQL Server, already. I checked ALL column names and didn't see any mistake.
To solve this problem you may do:
Check all columns names - yes, problem can be just in it. By the way, you will have an Error if its true.
Add new Database in Database (right IDE side) and connect to your data source.
Check your Persistence (bottom left corner in "Intellij IDEa"), press Assign Data... and use in Data Source not default source, but exactly yours.
If you have already connected database (MS Server, for example) - reconnect. Yes, its useful too.
Now, if your problem still annoying you - open File - Invalidate Caches / Restart and choose blue button Invalidate and Restart.
P.S.: If you use russian names for your table columns in database - write them as #Column(name = "[...]") and in SQL #Query put N before value in "" or write name in brackets. But the best idea - use just English!

How to do a Hibernate nested select?

Not sure if I worded the question correctly but i'm working with a postgres database
I'm looking for the equivalent of the following sql statement.
Select * from track where id in (Select track_id from track_item where item_time between x and y).
I'm new to hibernate and i've tried doing this using a Hibernate Query and using Criteria and failed both ways.
If there is an awnser using both methods it would be nice to see both examples as I'm trying to learn how to use both.
This is the create table information for the two tables
CREATE TABLE track (
id bigint NOT NULL,
track_uuid text,
track_number text,
track_exercise_indicator_id bigint NOT NULL,
track_simulation_indicator_id bigint NOT NULL,
track_status_id bigint,
last_modified timestamp with time zone DEFAULT timezone('utc'::text, now())
);
CREATE TABLE track_item (
id bigint NOT NULL,
track_item_type_id bigint NOT NULL,
item_time bigint NOT NULL,
frame_number bigint,
image_source text,
last_modified timestamp with time zone DEFAULT timezone('utc'::text, now()),
track_item_uuid character varying(200) NOT NULL,
track_id bigint NOT NULL
);
ALTER TABLE ONLY track_item
ADD CONSTRAINT track_item_track_id_fkey FOREIGN KEY (track_id) REFERENCES track(id);
ALTER TABLE ONLY track_item
ADD CONSTRAINT track_item_track_item_type_id_fkey FOREIGN KEY (track_item_type_id) REFERENCES track_item_type(id);
The java classes generated from the above table are.
#Entity
#Table(name = "track", schema = "d2d")
public class Track implements java.io.Serializable {
/**
* ID.
*/
private static final long serialVersionUID = 2313376497269789747L;
private long id;
private TrackSimulationIndicator trackSimulationIndicator;
private TrackStatus trackStatus;
private TrackExerciseIndicator trackExerciseIndicator;
private String trackUuid;
private String trackNumber;
private Date lastModified;
private Set<TrackMessageToTrackMapping> trackMessageToTrackMappings = new HashSet<TrackMessageToTrackMapping>(
0);
private Set<TrackInterval> trackIntervals = new HashSet<TrackInterval>(0);
private Set<AnomalyToTrackMapping> anomalyToTrackMappings = new HashSet<AnomalyToTrackMapping>(
0);
}
#Entity
#Table(name = "track_item", schema = "d2d")
public class TrackItem implements java.io.Serializable {
/**
* ID.
*/
private static final long serialVersionUID = 8469898950069782997L;
private long id;
private TrackItemType trackItemType;
private long itemTime;
private Long frameNumber;
private String imageSource;
private String trackItemUUID;
private Track track;
private Date lastModified;
private Set<TrackPoint> trackPoints = new HashSet<TrackPoint>(0);
private Set<TrackInformation> trackInformations = new HashSet<TrackInformation>(
0);
}
Your query should use joins to be more efficient, and be more easily translatable in HQL:
select distinct t.* from track t
inner join track_item item on t.id = item.track_id
where item.item_time between 100 and 200
This SQL query would translate to HQL as:
select distinct t from Track t
inner join t.items item
where item.time between 100 and 200
And in Criteria:
Criteria c = session.createCriteria(Track.class, "t");
c.setResultTransformer(criteria.DISTINCT_ROOT_ENTITY);
c.createAlias("t.items", "item");
c.add(Restrictions.between("item.time", 100L, 200L);
EDIT:
you've mapped the association as a ManyToOne association from TrackItem to Track. The inverse OneToMany association from Track to TrackItem doesn't exist, so the above queries won't work. The following HQL would work though:
select distinct t from Item item
inner join item.track t
where item.time between 100 and 200
You can't translate such a query to Criteria though, so you'd better make the association bidirectional: there's no reason for a track to not know about its items.
A colleague of mine came up with this Criteria solution below which works. The Solution JB Nizet posted for HQL statement works once he updates the table name and the reference to itemTime. The HQL query is posted at the bottom of this also.
/**
* #param p_startTime The date and time in ms
* #param p_endTime The date and time in ms
* #param p_session the session
* #return Returns the latest valid rule for the specified date time
* #throws IOException
*/
#SuppressWarnings("unchecked")
public static List<Track> loadAllTracksByDateRange(final long p_startTime,
final long p_endTime, final Session p_session) throws IOException {
// create the criteria
final Criteria criteria = p_session.createCriteria(TrackItem.class);
// set projection
criteria.setProjection(Projections.distinct(Projections
.property("track")));
// add the restriction
criteria.add(Restrictions.ge("itemTime", p_startTime));
criteria.add(Restrictions.le("itemTime", p_endTime));
return criteria.list();
}
HQL Solution:
Select distinct t
from TrackItem item inner join item.track t
where item.itemTime between 100L and 200L;
You can do nested selects with the DetachedCriteria class:
Session s = obtainSession();
Criteria c = s.createCriteria(Track.class);
DetachedCriteria dc = DetachedCriteria.forClass(TrackItem.class);
dc.setProjection(Property.forName("track"));
dc.add(Restrictions.between("itemTime", x, y));
c.add(Subqueries.propertyIn("id", dc))
Look at questions
diff between criteria and detached criteria in hibernate? and
when to use detached criteria in hibernate?
and hibernate documentation Chapter 15.8
for details

hibernate and oracle sequence GenericGenerator creates gap

I've mapped my class as follow (omitted other fields as only ID matters):
#Entity
#Table(name = "MODEL_GROUP")
#Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class SettlementModelGroup implements Serializable
{
#Id
#GeneratedValue(generator = "MODEL_GROUP_SEQ", strategy = GenerationType.SEQUENCE)
#GenericGenerator(name = "MODEL_GROUP_SEQ",
strategy = "sequence",
parameters = #Parameter(name = "sequence", value = "SEQ_MODEL_GROUP_MODEL_GROUP_ID"))
#Column(name = "MODEL_GROUP_ID", nullable = false)
private Integer modelId;
}
when I'm saving new object:
Integer modelGroupId = sessionFactory.getCurrentSession().save( modelGroup );
System.out.println( modelGroupId );
ID is set as for example 23, but when I look at the database it is actually 24. This is leading to many problems, as I'm using this ID later on. Any idea why it is making this gap?
SQL logs show that everything is fine (I thinks so):
Hibernate:
select
SEQ_MODEL_GROUP_MODEL_GROUP_ID.nextval
from
dual
Hibernate:
insert
into
MODEL_GROUP
(DOMAIN_ID, DESCRIPTION, NAME, PERIOD_TYPE_ID, MODEL_GROUP_TYPE_ID, STATUS_ID, OWNER_ID, MODEL_GROUP_ID)
values
(?, ?, ?, ?, ?, ?, ?, ?)
Trigger and Sequence:
CREATE SEQUENCE "SEQ_MODEL_GROUP_MODEL_GROUP_ID"
INCREMENT BY 1
START WITH 1
NOMAXVALUE
MINVALUE 1
NOCYCLE
NOCACHE
NOORDER
;
CREATE OR REPLACE TRIGGER "TRG_MODEL_GROUP_MODEL_GROUP_ID"
BEFORE INSERT
ON "MODEL_GROUP"
FOR EACH ROW
WHEN (NEW."MODEL_GROUP_ID" is NULL)
BEGIN
SELECT "SEQ_MODEL_GROUP_MODEL_GROUP_ID".NEXTVAL
INTO :NEW."MODEL_GROUP_ID"
FROM DUAL;
END;
Apparently, when Hibernate ask your database for nextValue of ID, it fires also Trigger. So when I ask for ID, I've got number 23 but when actually saving to database by commiting transaction, it is increased again so I've got 24. Solution is described here:
HIbernate issue with Oracle Trigger for generating id from a sequence
To make it work correctly, I changed Trigger:
CREATE OR REPLACE TRIGGER "TRG_MODEL_GROUP_MODEL_GROUP_ID"
BEFORE INSERT
ON "MODEL_GROUP"
FOR EACH ROW
WHEN (NEW."MODEL_GROUP_ID" is NULL)
BEGIN
SELECT "SEQ_MODEL_GROUP_MODEL_GROUP_ID".NEXTVAL
INTO :NEW."MODEL_GROUP_ID"
FROM DUAL;
END;

Automatically Insert first row soon after table is created / recreated using Hibernate

I want Username = Administrator and Password = admin, soon after table is created (or whenever table is recreate).
Is there any way to insert first row using following code. I do not want to use a separate insert query
Is there any constraint in Hibernate to restrict user from deleting (first) row
#Entity
#Table(name = "Users")
public class Users implements Serializable {
#Id
#Column(name = "Username", unique = true, nullable = false)
private String username;
#Column(name = "Password", nullable = false)
private String password;
/**************** getter & setter ************/
}
What you seem to be looking for is called fixtures. With Hibernate you can supply import.sql file on your classpath with your initial data (insert statements).
There's a bit more information on the JBoss' site.
The import.sql file is a simple text file with SQL statements, one line per statement:
insert into users (id, username) values (1, 'administrator');
insert into users (id, username) values (2, 'user');
...

Categories

Resources