SQL syntax error initializing DB before unit Tests - java

I have created a .sql for preparing my DB for testing.
here a part of the .sql which produces the error:
DROP TABLE IF EXISTS announcement;
CREATE TABLE announcement (
id int(11) NOT NULL AUTO_INCREMENT,
date datetime DEFAULT NULL,
title varchar(255) DEFAULT NULL,
content mediumtext,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
LOCK TABLES announcement WRITE;
INSERT INTO announcement VALUES (1,'2015-07-29 10:59:16','Test Anno ','some text');
UNLOCK TABLES;
when executed in Mysql Workbench this scipt works fine.
however when executed via hibernate:
String sqlScript = readFile("dump.sql", Charset.forName("UTF8"));
//System.err.println(sqlScript);
Query q = em.createNativeQuery("BEGIN " + sqlScript + "END;");
q.executeUpdate();
I get:
2015-08-06 16:15:55 ERROR SqlExceptionHelper:146 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DROP TABLE IF EXISTS announcement;
CREATE TABLE announcement (
id int(11) NO' at line 1
I am using:
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect");
jpaProperties.put("hibernate.enable_lazy_load_no_trans", true);
Can someone help me out here?
thanks.

As stated by mustaccio BEGIN and END statements are not allowed outside of stored procedueres. See: Hibernate multiple native SQL statements

Related

Java - MariaDB Perfoming slow with Hibernate criteria

Environment:
mariadb-java-client-2.7.0
DB : MariaDB 10.5.7
ojdbc8 - Oracle 11.2.0.3.0 JDBC 4.0
DB : Oracle Database 11g
Hibernate 4.3.8
Code :
Session session = sessionFactory.openSession();
Criteria fetchCriteria = session.createCriteria("Student");
Disjunction disjunction = Restrictions.disjunction();
for (int i = 1; i <= 10000; i++) {
Conjunction conjunction = Restrictions.conjunction();
conjunction.add(Restrictions.eq("RollNumber", i+""));
disjunction.add(conjunction);
}
fetchCriteria.add(disjunction);
long start1 = System.currentTimeMillis();
List resultList = fetchCriteria.setFirstResult(0).setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP).list();
long end1 = System.currentTimeMillis();
System.out.println("Time took :"+(end1-start1) +"ms");
Issue
If i run above code with Hibernate 4.3.8 + Oracle 8 it taking less than 5000 milliseconds.
If i run above code with Hibernate 4.3.8 +mariadb-java-client-2.7.0 it taking more than 40,000 milliseconds.
Extra Configuration :
I have set hibernate.jdbc.fetch_size to 100 in hibernate.cfg.xml
along with jdbc URL ,username and password.
Findings:
The query generated in both cases are same and if i execute those
query with SQL Client it takes 10-11 seconds for ORACLE and 41-42 seconds for MariaDB.
The query which is generated by both database if i invoke using JDBC
program (both for ORACLE and MariaDB) it is taking approx 600 milliseconds
Note: Both tables (Oracle and MariaDB) have 15,000 records.
Can anyone help me why MariaDB is taking time?
or some extra settings are required to improve the MariaDB performance.
I have tried defaultFetchSize which is mentioned in https://mariadb.com/kb/en/about-mariadb-connector-j/ but no luck.
SQL Query Generated by the databases:
select this_.rollNo as RollNo1_0_0_, this_.VersionID as Version2_0_0_,
this_.Name as Name3_0_0_, this_.dept as dept4_0_0_,
this_.favSubj as favSubj5_0_0_,
this_.ID as ID33_0_0_
from Student this_
where ((this_.ID='1')
or (this_.ID='2')
or (this_.ID='3')
or ....
or (this_.ID='10000')
MariaDB DDL
CREATE TABLE `student` (
`RollNo` bigint(20) NOT NULL ,
`VersionID` bigint(20) NOT NULL,
`Name` varchar(100) COLLATE ucs2_bin DEFAULT NULL,
`dept` varchar(100) COLLATE ucs2_bin DEFAULT NULL,
`favSubj` varchar(100) COLLATE ucs2_bin DEFAULT NULL,
`ID` varchar(100) COLLATE ucs2_bin DEFAULT NULL,
PRIMARY KEY (`RollNo`),
UNIQUE KEY `UK_student` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=20258138 DEFAULT CHARSET=ucs2 COLLATE=ucs2_bin
Oracle DDL
CREATE TABLE student (
RollNo NUMBER(19,0),
VersionID NUMBER(19,0) NOT NULL ENABLE,
Name VARCHAR2(100),
dept VARCHAR2(100),
favSubj VARCHAR2(100),
ID VARCHAR2(100),
PRIMARY KEY ("RollNo"),
CONSTRAINT "UK_student" UNIQUE ("ID")
)
MariaDB explain select query output
id
select_type
table
type
possible_keys
key
key_len
ref
rows
Extra
1
SIMPLE
this_
range
UK_Student
UK_Student
203
NULL
10000
Using index condition
An OR with 10K items takes a long time to parse. Faster would be an IN:
where this_.ID IN ('1', '2', ..., '10000')
However, even that is likely to take a long time to run.
In the case of MariaDB, I think the Optimizer will say
Oh, that's too many items for me to look up each one, so
I will, instead, simply scan the table, checking each row for an ID in that list (using some kind of efficient lookup in the 10K-long list).
However, if there are 20M rows in the table, that will take a long time.
Can you provide the query plan (EXPLAIN) so we can confirm what I am hypothecating?
This seems logical and faster, but will not work correctly:
where this_.ID BETWEEN '1' AND '10000'
because it is a VARCHAR!!
Performance -- Make id an INT, not a VARCHAR!

JDBC. Replace in all rows value of the column

Java 11. PostgreSQL.
Having following table in db:
TABLE public.account (
id bigserial NOT NULL,
account_id varchar(100) NOT NULL,
display_name varchar(100) NOT NULL,
is_deleted bool NULL DEFAULT false,
);
There are about 1000 rows in this table. In the code I have a static method, which return random string - Helper.getRandomName()
How, using JDBC, in this table (public.account) for all rows replace "display_name" value with value of Helper.getRandomName()?
This is a SQL question. You need to run an update query:
UPDATE public.account set display_name = ?
And provide the new name as the parameter. The absence of a WHERE clause means that all rows will be affected.
If you want to do this for each row individually, then it's harder. You'll want to do a select statement to find all the IDs, and then you can prepare a batch of updates using JDBC, adding a where clause for each ID.
JDBC is just a thin Java wrapper around plain SQL execution.

Column not found after update db

I'm new to java . i've two questions . i'm using flyway and h2 db i added two file sql one of them to create table with two columns like that
CREATE TABLE contacts (
id bigint auto_increment NOT NULL,
name varchar(128) NOT NULL,
PRIMARY KEY(id)
);
and the other is to alter new column like that
ALTER TABLE contacts
ADD COLUMN contacts Varchar(255);
1- i used flyway.migrate worked fine but i faced mismatch so i used flyway.repair() is that normal to use it every time ?
2- when i wrote statment sql for executing insert sql command like that
stmt.execute("INSERT INTO contacts(name,contacts) VALUES('ABC','ABC#yahoo.com')");
i got
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Column "CONTACTS" not found; SQL statement:
INSERT INTO contacts(name,contacts) VALUES('ABC ','ABC#yahoo.com') [42122-173]
You need to add AFTER in your second sql file.
ALTER TABLE contacts
ADD COLUMN contacts Varchar(255) AFTER name;

Liquibase sql precondition is not checked

I have multiple changelogs and one of the change log has the precondition on it to check if table exists, if so, skip running the migration.
My change log file
--liquibase formatted sql
--preconditions onFail:MARK_RAN onError:MARK_RAN
--precondition-sql-check expectedResult:0 select COUNT(*) C from dba_tables where UPPER(table_name) = 'PERSON' and upper(owner) = 'INT'
--changeset nvoxland:3
create table int.person (
id int not null primary key,
firstname varchar(80),
lastname varchar(80) not null,
state varchar(2)
);
The precondition is never checked, it directly goes to creating the 'person' table. I have this table in this db instance because of the refresh, i'd like this migration to run if it does not exist and skip on precondition.
error I get
C:\Project\Tools\liquibase-3.5.3-bin>liquibase --driver=oracle.jdbc.driver.Oracl
eDriver --changeLogFile=C:\Project\Tools\Migrations\liquibase\master.xml --url="
jdbc:oracle:thin:#database:1521:name" --username=user --password=dpass migrate
Unexpected error running Liquibase: ORA-00955: name is already used by an existi
ng object
[Failed SQL: create table int.person (
id int not null primary key,
firstname varchar(80),
lastname varchar(80) not null,
state varchar(2)
)]
Never mind, I solved this myself
The ordering of the precondition was important, updated to the following, it ran fine this time
--liquibase formatted sql
--changeset nvoxland:3
--preconditions onFail:MARK_RAN onError:MARK_RAN
--precondition-sql-check expectedResult:0 select COUNT(*) C from dba_tables where UPPER(table_name) = 'PERSON' and upper(owner) = 'INT'
create table int.person (
id int not null primary key,
firstname varchar(80),
lastname varchar(80) not null,
state varchar(2)
);
-- noinspection SqlNoDataSourceInspectionForFile
can cause the same problem
remove it

#1467 - Failed to read auto-increment value from storage engine

I was trying to create a new object and this error appeared:
java.sql.sqlexception failed to read auto-increment value from storage engine
So I went to the phpMyAdmin to create the object there and the same showed up:
MySQL said: Documentation
1467 - Failed to read auto-increment value from storage engine
then I clicked on edit, and it was there:
INSERT INTO `reservation`.`room` (`idroom`, `number`, `floor`, `description`, `characteristics`, `cost`, `status`, `type`) VALUES (NULL, '114', '3', 'ss', 'ss', '550.00', 'Available', 'ss')
(idroom is supposed to be auto-incremented.)
I already read other posts where they say I have to put this:
ALTER TABLE `table_name` AUTO_INCREMENT = 1
but I have no idea where to put that. Is there a better solution?
Your INSERT statement is wrong. Since idroom is AUTO_INCREMENT; you must not include it in the column list on your insert command. Your insert statement should look like below. Notice that I have removed idroom column from insert column list and not passing NULL as well in value list.
INSERT INTO `reservation`.`room` (`number`, `floor`, `description`,
`characteristics`, `cost`, `status`, `type`)
VALUES ('114', '3', 'ss', 'ss', '550.00', 'Available', 'ss')
I also struggled with this problem and searched, and didn't find anything. Then the following worked for me; I guess it might work for your problem. Thx.
1st:
-delete (before backup)->all data from your database.
-try to run your Java program again, or any program you want.
If it fails then go to 2nd.
2nd:
- backup all data from your table
- delete table completely
- create table again; example shown below:
CREATE TABLE `users` (
`id` int(6) NOT NULL,
`f_name` varchar(30) NOT NULL,
`l_name` varchar(30) NOT NULL,
`address` varchar(50) DEFAULT NULL,
`phone_num` varchar(12) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL
);
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
AUTO_INCREMENT for table `users`
ALTER TABLE `users`
MODIFY `id` int(6) NOT NULL AUTO_INCREMENT;

Categories

Resources