In memory SQLITE in a Spring Boot application not working - java

I am trying to setup SQLITE as an in-memory database in my spring-boot application. But when i try to query the database then it gives me an error "No such table"
Can someone please recommend what am i doing wrong? I need to have SQLITE as a in memory only and we only use jdbc in our project.
Here is my code:
application.properties
spring.datasource.url=jdbc:sqlite:memory
spring.datasource.username=
spring.datasource.password=
spring.datasource.platform=sqlite
spring.datasource.driver-class-name=org.sqlite.JDBC
MyRepo.java
#Repository
public class MyRepo{
#Autowired
private NamedParameterJdbcTemplate namedJdbc;
public String getUserName() throws Exception{
String userName = null;
String sql = "SELECT username FROM emp WHERE username=:name";
MapSqlParameterSource paramSource = new MapSqlParameterSource();
paramSource.addValue("name", "tuser");
userName = this.namedJdbc.query(sql, paramSource, (rs) -> {
String name = null;
while (rs.next()) {
name = rs.getString("username").trim();
return name;
}
return null;
});
return userName;
}
}
UserDaoTest.java
#SpringBootTest
public class UserDaoTest {
#Autowired
private MyRepo rep;
#Test
public void testFindByname() throws Exception{
rep.getUserName();
}
}
I also have schema.sql and data.sql files under src/main/resources
schema.sql
DROP TABLE IF EXISTS emp;CREATE TABLE IF NOT EXISTS emp(username VARCHAR(20), empId BIGINT, PRIMARY KEY(empId) )
data.sql
INSERT INTO emp(username,empId) VALUES ('tuser',1001);
Exception that i am getting:
PreparedStatementCallback; uncategorized SQLException for SQL [SELECT username FROM Chats WHERE username=?]; SQL state [null]; error code [1]; [SQLITE_ERROR] SQL error or missing database (no such table: Chats)

well, I am shooting in the dark but looks like you need to add the schema for 'Chats' table as well to your schema.sql

https://sqlite.org/inmemorydb.html
The database ceases to exist as soon as the database connection is closed. Every :memory: database is distinct from every other. So, opening two database connections each with the filename ":memory:" will create two independent in-memory databases.
Your issue might be with spring boot opening multiple connections due to its connection pool configuration. If you're using hikari connection pool (default in newer spring boot versions), try adding these properties
spring.datasource.hikari.maximum-pool-size=1
spring.datasource.hikari.max-lifetime=0

Related

Not able to insert data in MSSQL using r2dbc (non spring)

I am new to r2dbc. I am trying to connect to MSSQL DB using R2DBC (non spring project) with reactor. It is not establishing the connection and also the data is not getting inserted into the table. I have tried by giving wrong table name as well, but there is no exception for it.
public Flux<MssqlResult> writetoDB() {
return createDBConnection().create()
.flatMapMany(c -> c.createStatement("INSERT INTO person (id, first_name, last_name) VALUES(#id, #firstname, #lastname)")
.bind("id", 1)
.bind("firstname", "Walter")
.bind("lastname", "White")
.execute()
.doFinally((st) -> c.close()))
.log();
}
private MssqlConnectionFactory createDBConnection() {
MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder()
.host("sample-host").username("testuser")
.password("testuser1").database("testDB").preferCursoredExecution(true).build();
MssqlConnectionFactory factory = new MssqlConnectionFactory(configuration);
return factory;
}
Kindly suggest what I am missing here.

Ran Java code in netbeans without any problems. Though the Table does not appear in Mysql Workbench

Please start by knowing I am a total beginner. The code that will be posted below is from "YouTube".
The code is to establish a connection to Mysql workbench database "mysql".
Purpose is to create a table with column names.
The project runs fine. Well! No visible hick-ups. The output window in Netbeans reads:
run:
Connected
Function complete.
BUILD SUCCESSFUL (total time: 1 second)
Can't negotiate MySQL Workbench documentation to possible reasons for not listed the Table. But still looking.
I replaced part of the "CREATE TABLE IF NOT EXISTS..." with "CREATE TABLE..."
The output window in Netbeans then reads:
run:
Connected
java.sql.SQLSyntaxErrorException: Table 'actors'
already exists
Function complete.
BUILD SUCCESSFUL (total time: 1 second)
package homemovies;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class HomeMovies {
public static void main(String[] args) throws
Exception { creatTable(); }
public static void creatTable() throws Exception{
try{
Connection con = getConnection();
PreparedStatement create =
con.prepareStatement("CREATE TABLE IF NOT EXISTS
Actors(id int NOT NULL AUTO_INCREMENT, "
+ "Fname varchar(255), Lname
varchar(255), PRIMARY KEY(id))");
create.executeUpdate();
}catch(Exception e){System.out.println(e);}
finally{System.out.println("Function
complete.");}
}
public static Connection getConnection() throws
Exception{
try{
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mysql";
String username = "username here";
String password = "password here";
Class.forName(driver);
Connection conn =
DriverManager.getConnection(url,username,password);
System.out.println("Connected");
return conn;
}catch(Exception e){System.out.println(e);}
return null;
}
}
Expect the table "Actors" to be listed in Tables section of MySQL Workbench.
I tried additional things like stopping the server, closing MySQL Workbench application; Restarting the application and the server. The Table "Actors" still continues not to show up where it should.
Please help.
Appreciate your time.
Thank you.
IF NOT EXISTS prevents error from occuring. You can check the manual here https://dev.mysql.com/doc/refman/8.0/en/create-table.html
If you try to run the query multiple times without IF NOT EXISTS in MySQL workbench, you would get a similar error.

Check if h2 database is corrupted and create new if corrupted

I'm a C# developer and need to maintain an existing Java Service application developed using spring boot framework. The responsible developer left the company some time ago so I have no possibility to get some help...
So far I have no experience with Java and the used spring boot framework.
What I need to achive:
Check if used h2 Database is corrupted
If corrupted: Delete the database and create a new empty one
I guess I need to implement the check and recreation in the main entry point
public static void main(String[] args) {
SpringApplication.run(MessageServiceApplication.class, args);
}
As I know spring-boot and Hibernate creates the db automatically on startup if the database does not exists. So far so good. Now I need to check if the database is corrupted. I thought about executing a query on the database and if I get an exception I recreate the database.
The Database is a h2 file database.
Hopefully I can get some assistance.
Edit #1
I thought about implementing a utils class which gets called on startup:
public class H2DbUtils {
public boolean IsH2FileDatabaseCorrupted()
{
boolean isCorrupted = false;
// Implement Logic to determine if db is corrupted
return isCorrupted;
}
public boolean ReCreateH2DatabaseFile()
{
boolean reCreated = false;
// Implement Logic to recreate db
return reCreated;
}
}
Calling this class on startup
public static void main(String[] args) {
H2DbUtils h2DbUtils = new H2DbUtils();
if(h2DbUtils.IsH2FileDatabaseCorrupted()) {
h2DbUtils.ReCreateH2DatabaseFile();
}
SpringApplication.run(MessageServiceApplication.class, args);
}
Update 2018-03-20
Currently found the following solution to achive this:
#Configuration
#Component
public class DataSourceBean {
#Autowired
private Environment currentEnvironment;
private final Logger logInstance = LoggerFactory.getLogger(this.getClass());
#Bean
#Primary
public DataSource dataSource()
{
DataSource dataSource = null;
try
{
// We try to get the Meta Data out of the database.
// If this fails the database is corrupted or has an other problem
// All in all this means we need to delete the current database file
// to avoid further problems.
dataSource = this.getDataSource();
dataSource.getConnection().getMetaData();
return dataSource;
}
catch (Exception ex)
{
logInstance.error("The h2 database file '{}' seems to be corrupted! Error: {}",
currentEnvironment.getProperty("dataBaseFile"),
ex.getMessage());
// dataBaseFile=./db/mydatabase.db
String databaseFilePath = String.format("%s.%s", currentEnvironment.getProperty("dataBaseFile"), "h2.db");
databaseFilePath = databaseFilePath.replace("/", "\\");
File databaseFile = new File(databaseFilePath);
if (databaseFile.exists()) {
File parentDirectory = new File(databaseFile.getParent());
if (parentDirectory.isDirectory()) {
try {
FileUtils.deleteDirectory(parentDirectory);
} catch (Exception fex) {
logInstance.error("Error occurred deleting the folder {}. Error: {}",
parentDirectory.getAbsolutePath(),
fex.getMessage());
}
}
}
dataSource = this.getDataSource();
}
finally {
return dataSource;
}
}
#ConfigurationProperties(prefix = "spring.datasource")
private DataSource getDataSource() {
return DataSourceBuilder.create()
.url(currentEnvironment.getProperty("spring.datasource.url"))
.driverClassName(currentEnvironment.getProperty("spring.datasource.driverClassName"))
.username(currentEnvironment.getProperty("spring.datasource.username"))
.password(currentEnvironment.getProperty("spring.datasource.password"))
.build();
}
It is possible to overwrite the DataSource bean and check database files
#Bean
#Primary // this will override the datasource autoconfiguration and use your own everywhere
public DataSource dataSource() {
// Open Connection
// Check Database
// Close Connection
// IF File corrupted delete files
// create regular data source
}
I've tried to add several listeners to the spring boot application, for example:
SpringApplication springApplication = new SpringApplication(testApplication.class);
springApplication.addListeners(new FailedEvent(testApplication.class));
SpringApplication.run(testApplication.class, args);
But I never get to one of this listeners in the startup of the spring application. As SpringApplication.run seems to initzialise the whole spring context it is also not possible to inject or get the configuration environment to get the connection string as the application stops within SpringApplication.run as the db is corrupted.
I assume that spring tries to initzialise hibernate and so on and fails to create a database connection as the db is corrupted
org.h2.jdbc.JdbcSQLException: Allgemeiner Fehler: "java.lang.RuntimeException: rowcount remaining=2 SYS"
General error: "java.lang.RuntimeException: rowcount remaining=2 SYS" [50000-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.196.jar:1.4.196]
at org.h2.message.DbException.get(DbException.java:168) ~[h2-1.4.196.jar:1.4.196]
at org.h2.message.DbException.convert(DbException.java:295) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Database.openDatabase(Database.java:307) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Database.<init>(Database.java:270) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Engine.openSession(Engine.java:64) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Engine.openSession(Engine.java:176) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Engine.createSessionAndValidate(Engine.java:154) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Engine.createSession(Engine.java:137) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.Engine.createSession(Engine.java:27) ~[h2-1.4.196.jar:1.4.196]
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:354) ~[h2-1.4.196.jar:1.4.196]
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:116) ~[h2-1.4.196.jar:1.4.196]
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:100) ~[h2-1.4.196.jar:1.4.196]
at org.h2.Driver.connect(Driver.java:69) ~[h2-1.4.196.jar:1.4.196]
This happens within the SpringApplicatio.run context. Before I found no chance to check if the db is corrupted and if so delete the database.

Exception while inserting a record in to Apache Ignite Cluster using JDBC connection

I've been struggling to run an insert query on Apache Ignite Cache using JDBC connection. I've created my Cache using the following configuration:
CacheConfiguration<Long, MyApplication> cacheCfg = new CacheConfiguration<>("SQL_PUBLIC_MYAPPLICATION");
cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setIndexedTypes(Long.class, MyApplication.class);
cacheCfg.setSqlSchema("PUBLIC");
cacheCfg.setCacheStoreFactory(FactoryBuilder.factoryOf(CacheMyApplicationStore.class));
cacheCfg.setReadThrough(true);
cacheCfg.setWriteThrough(true);
FifoEvictionPolicy<Long, MyApplication> eviction = new FifoEvictionPolicy<Long, MyApplication>();
eviction.setMaxSize(100_000);
IgniteCache<Long, MyApplication> cache = getIgnite().getOrCreateCache(cacheCfg);
cache.loadCache(null, 100_000);
MyApplication.java
public class MyApplication {
#QuerySqlField(index = true,orderedGroups = {#QuerySqlField.Group(name = "idx3", order = 0)})
private Long ID;
#QuerySqlField(index = true,orderedGroups = {#QuerySqlField.Group(name = "idx3", order = 1)})
private String NAME;
#QuerySqlField
private String DESCRIPTION;
}
I was able to update or delete a record in the Cache using JDBC connection but the insert is not working. I'm getting an exception when I try to insert using the following code:
Connection conn = DriverManager.getConnection("jdbc:ignite:thin://url:4000");
try (PreparedStatement stmt = conn.prepareStatement("insert into MyApplication (ID, NAME, DESCRIPTION) values (1, 'TestApp', 'To be deleted')")) {
stmt.setLong(1, 1L);
stmt.setString(2, "TestApp");
stmt.setString(3, "To be deleted");
stmt.executeUpdate();
}
Exception:
[17:15:14,894][ERROR][sql-connector-#58%agrid%][JdbcRequestHandler] Failed to execute SQL query [reqId=1, req=JdbcQueryExecuteRequest [schemaName=null, pageS ize=1024, maxRows=0, sqlQry=insert into MyApplication (ID, NAME, DESCRIPTION) values (?,?,?), args=[1, TestApp, To be deleted]]] class org.apache.ignite.internal.processors.query.IgniteSQLException: Failed to execute DML statement [stmt=insert into MyApplication (ID, NAME, DESCRIPTION) values (?,?,?), params=[1, TestApp, To be deleted]]]
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.queryDistributedSqlFields(IgniteH2Indexing.java:1324)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$6.applyx(GridQueryProcessor.java:1856)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$6.applyx(GridQueryProcessor.java:1852)
at org.apache.ignite.internal.util.lang.IgniteOutClosureX.apply(IgniteOutClosureX.java:36)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.executeQuery(GridQueryProcessor.java:2293)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.querySqlFieldsNoCache(GridQueryProcessor.java:1860)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.executeQuery(JdbcRequestHandler.java:188)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.handle(JdbcRequestHandler.java:122)
at org.apache.ignite.internal.processors.odbc.SqlListenerNioListener.onMessage(SqlListenerNioListener.java:152)
at org.apache.ignite.internal.processors.odbc.SqlListenerNioListener.onMessage(SqlListenerNioListener.java:44)
at org.apache.ignite.internal.util.nio.GridNioFilterChain$TailFilter.onMessageReceived(GridNioFilterChain.java:279)
at org.apache.ignite.internal.util.nio.GridNioFilterAdapter.proceedMessageReceived(GridNioFilterAdapter.java:109)
at org.apache.ignite.internal.util.nio.GridNioAsyncNotifyFilter$3.body(GridNioAsyncNotifyFilter.java:97)
at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
at org.apache.ignite.internal.util.worker.GridWorkerPool$1.run(GridWorkerPool.java:70)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: class org.apache.ignite.IgniteCheckedException: Key is missing from query
at org.apache.ignite.internal.processors.query.h2.dml.UpdatePlanBuilder.createSupplier(UpdatePlanBuilder.java:331)
at org.apache.ignite.internal.processors.query.h2.dml.UpdatePlanBuilder.planForInsert(UpdatePlanBuilder.java:196)
at org.apache.ignite.internal.processors.query.h2.dml.UpdatePlanBuilder.planForStatement(UpdatePlanBuilder.java:82)
at org.apache.ignite.internal.processors.query.h2.DmlStatementsProcessor.getPlanForStatement(DmlStatementsProcessor.java:438)
at org.apache.ignite.internal.processors.query.h2.DmlStatementsProcessor.updateSqlFields(DmlStatementsProcessor.java:164)
at org.apache.ignite.internal.processors.query.h2.DmlStatementsProcessor.updateSqlFieldsDistributed(DmlStatementsProcessor.java:222)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.queryDistributedSqlFields(IgniteH2Indexing.java:1321)
... 17 more
Any help would be greatly appreciated.
Just configure the cache and SQL indexes using CREATE TABLE and CREATE INDEX commands, especially, if you plan access Ignite with SQL operations mostly.
If key-value, computational or machine learning APIs are still required then check up this project that showcases how to do that when the caches are defined using SQL DDL commands.
The root cause is the following:
Caused by: class org.apache.ignite.IgniteCheckedException: Key is missing from query
All the values you provided in the INSERT statement belong to value object, therefore Ignite fails to create a key object for the entry and throws this exception.
To fix this you should create a class for the key object (e.g. MyApplicationKey) and move ID field there.

Cassandra JDBC preparedstatment error

I have a following cassandra table "users" defined in keyspace "chemdb"
CREATE TABLE users (
userid text PRIMARY KEY,
passwd text,
fname text,
lname text,
creationdate timestamp,
isactive text
);
I created a java class JDBConnec.java to connect jsp with cassandra using jdbc:
package dbclasses;
import java.sql.*;
import java.lang.*;
import java.io.*;
public class JDBConnec {
public Statement stmt=null;
public ResultSet rs=null;
public Connection con=null;
public PreparedStatement pstmt = null;
public JDBConnec()
{
try
{
Class.forName("org.apache.cassandra.cql.jdbc.CassandraDriver");
con = DriverManager.getConnection("jdbc:cassandra://127.0.0.1:9160/chemdb","okkkkk","12345");
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
}
The above class is succesfully compiling.
However in my jsp file, when I use the following code to select record from database by using Preparedstatements, I get the below mentioned error:
JDBConnec db = new JDBConnec();
String query = "select * from users where userid=?";
db.pstmt = db.con.prepareStatement(query);
db.pstmt.setString(1, "henry");
db.rs = db.pstmt.executeQuery();
It gives following error
InvalidRequestException(why:Undefined name userid in where clause ('userid EQ ?'))
Does cassandra jdbc driver support preparedstatments in jsp? Any thoughts on why this error is occuring. Thanks in advance.
Cassandra version: 2.0.8
Java: 7
Apache tomcat: latest downloaded yesterday
I was able to figure out problem. I just changed the query from
String query = "select * from users where userid=?";
to
String query = "select userid, passwd from chemdb.users where userid=?";
and it worked fine.
Thanks!

Categories