I have a web application using an embedded (in-memory) H2 database. It seems like the H2 DB is set up correctly on Tomcat startup (no errors in server log), but when accessing the DB (through the application) it seems to be "empty" (no application tables nor data available, even though the log states that they have been created/inserted).
How can I check the H2 DB is really set up or not? I've been trying to connect to the DB using a DB tool (e.g. H2 console, DB Visualizer) but I am not sure about the proper DB connection string or username/pw as it is not explicitly defined in the project.
By raising the log level in the server log, I could at least retrieve this information:
Creating new JDBC Driver Connection to [jdbc:h2:mem:myDataSource;DB_CLOSE_DELAY=-1]
Not sure though whether I am really connected or not because I could pass any user/pw combination and can still "connect"? Probably it's not the right way, because I can only retrieve schemas INFORMATION_SCHEMA and PUBLIC on the DB?
You cannot use a memory database, even a named one, because as soon as the last SQL connection using it is closed, the database will be purged. If you open it again, the only thing you'll see is information_schema tables and views.
I suggest you use embedded mode instead: the database will be persisted, and you can later on open it in another process, a DB viewer, or even in tcp mode if you started H2 server.
As you're using Tomcat, I just wrote today an answer to a similar issue (Embedding an H2 Database within the WEB-INF Directory).
Might be helpful to you: https://stackoverflow.com/a/30638808/3956551
Related
Apparently, using AttachDbFilename and user instance in your connection string is a bad way to connect to a DB. I'm using SQL server express on my local machine and it all seems to work fine. But what's the proper way to connect to SQL server then?
Thanks for your explanation.
Using User Instance means that SQL Server is creating a special copy of that database file for use by your program. If you have two different programs using that same connection string, they get two entirely different copies of the database. This leads to a lot of confusion, as people will test updating data with their program, then connect to a different copy of their database in Management Studio, and complain that their update isn't working. This sends them through a flawed series of wild goose chase steps trying to troubleshoot the wrong problem.
This article goes into more depth about how to use this feature, but heed the very first note: the User Instance feature has been deprecated. In SQL Server 2012, the preferred alternatives are (in this order, IMHO):
Create or attach your database to a real instance of SQL Server. Your connection string will then just need to specify the instance name, the database name, and credentials. There will be no mixup as Management Studio, Visual Studio and your program(s) will all be connecting to a single copy of the database.
Use a container for local development. Here's a great starter video by Anna Hoffman and Anthony Nocentino, and I have some other resources here, here, and here. If you're on an M1 Mac, you won't be able to use a full-blown SQL Server instance, but you can use Azure SQL Edge if you can get by with most SQL Server functionality (the omissions are enumerated here).
Use SqlLocalDb for local development. I believe I pointed you to this article yesterday: "Getting Started with SQL Server 2012 Express LocalDB."
Use SQL Server Compact. I like this option the least because the functionality and syntax is not the same - so it's not necessarily going to provide you with all the functionality you're ultimately going to want to deploy. Compact Edition is also deprecated, so there's that.
Of course if you are using a version < SQL Server 2012, SqlLocalDb is not an option - so you should be creating a real database and using that consistently. I only mention the Compact option for completeness - I think that can be almost as bad an idea as using AttachDbFileName.
EDIT: I've blogged about this here:
Bad Habits : Using AttachDBFileName
In case someone had the problem.
When attaching the database with a connection string containing AttachDBFile
with SQLEXPRESS, I noticed this connection was exclusive to the ASP.NET application that was using the database. The connection did block the access to all other processes on the file level when made with System.Data.SqlClient as provider.
In order to assure the connection to be shareable with other processes
instead use DataBase to specify the database name in your connection string
Example or connection string :
Data Source=.\SQLEXPRESS;DataBase=PlaCliGen;User ID=XXX;password=ZZZ; Connect Timeout=30
,where PlaCliGen is the name (or logical name) by which SQLEXPRESS server knows the database.
By connecting to the data base with AttachDBFile giving the path to the .mdf file
(namely : replacing DataBase = PlacliGen by AttachDBFile = c:\vs\placligen\app_data\placligen.mdf) the File was connected exclusively and no other process could connect to the database.
I have a bunch of legacy access based databases that I've been using for years without issue - queries have been running between them for years using ODBC/DAO/ADO. Now suddenly in the last few days, I've started getting the "The database has been placed in a state by user...." error on a bunch of them.
I have tried to narrow the problem down, but it seems to be getting worse. I have tried making a local copy of the database file, opening it, and then on the same machine, trying to create an ODBC connection to it, and get the error. I have also tried running successive queries on the database and still get the same thing (copy of the file on my local machine, so there is only my single connection, basically connect to the database, run a query, close the connection, wait 2 minutes, then try to open a new connection - FAIL - so it is definitely not a multi user limit problem or anything like that.
The issue is consistent across multiple platforms (directly in MS Access (2010 and 2013), with Excel (2010 and 2013) queries to the Access DB, and with Windows Forms VB.net applications trying to query the access DB (through datasets, OLEDB, and ADO)
Until this week all of these applications were working as designed and had been for years- I am the only Dev working on this stuff, so I know that nothing in the programming has changed, so it must be an external issue.
The back end databases reside on a shared server drive (server is running Windows Server 2008) - and we have had no other connection issues to the server or network; it is limited to connections to access database files.
Does anyone know if something has changed lately (in the last week or so) with the ODBC drivers? Maybe an MS update?
Thanks in advance!
It seems that you can fix this issue by buffering the Access binary. Use the Binary.Buffer function in a query that defines your Access database, then reference that query in order to use the binary in a query that pulls each table. Note: I also define parameters for my folder path and file names.
For example:
//myDbBinary
let
Source = Binary.Buffer(File.Contents(DataFolder_param & FileName_param),
[CreateNavigationProperties=true]))
in
Source
// Table1 Query
let
Source = Access.Database(myDbBinary, [CreateNavigationProperties=true]),
_Table1 = Source{[Schema="",Item="Table1"]}[Data]
in
_Table1
The source is this
(I am a sql noob and I just can not figure this out on my own)
For some time now I have been trying to establish a connection to a SQL database in codename one but to no avail. First I tried connecting to a MariaDB database from one.com. All that's needed for the connection is
Database db = Display.getInstance().openOrCreate("databaseName");
if I am not mistaken, but I am guessing this implies that I have somehow already established a connection to the database. This is not the case however so it creates a new .sql file, right? I can recall that you can connect to a database in the services tab in Netbeans. I chose the MySQL(Connector/ J Driver) which should work with MariaDB, or should it? I entered all my data and i says that it can not establish connection to the database.
the error i get
So I thought I might as well try using localhost. I used XAMPP to host a database and connected in the netbeans services tab.
connected?
Now testing was needed to see if this works. I started the SQL journey with this https://www.codenameone.com/manual/files-storage-networking.html#_sql and integrated the part after "You can probably integrate this code into your app as a debugging tool". I changed database name to "mybase" (it's existance can be confirmed in picture 2). Ran the app, opened the dialog, entered "select ID from customers" and got: java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such table: customers) It does not get past the first call to "executeQuery". The customers table definitely exists so what am I missing to establish connection?
I really need instructions to connect to the localhost database and ideally also to the one hosted by my webhost provider.
Thanks,
Jona
The Database class is to access the SQLite DB on the mobile device. To connect to external databases, you'd have to do something different, such as a ConnectionRequest or Socket I think.
I've performed multiple searches and read numerous pages and tried loads of different configurations and nothing seems to solve a nuisance problem we have. We have a SQL server (2008 R2 v10.50.4000) that has several linked servers to several different access databases on a different server. They are all set up using UNC paths and they work...for a time.
At some point, something happens and then we can no longer access the databases and the only way I have found to solve this is to restart the SQL server service, which obviously isn't ideal in a production environment. This is the exact error message we get when we try to access it:
OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "HIDDEN" returned message "The Microsoft Access database engine cannot open or write to the file '\servername\path01\path02\path03\databasename.mdb'. It is already opened exclusively by another user, or you need permission to view and write its data.".
Yet it works absolutely fine again if I restart the SQL Server service, so I know the settings are correct. I strongly suspect it has something to do with the Microsoft ACE driver because they all (the Access database linked servers) stop working at the same time - even though they all look at different files.
At this point I'm willing to try anything.
I am having problems with creating an in memory table, using H2 database, and accessing it outside of the JVM it is created and running in.
The documentation structures the url as jdbc:h2:tcp://<host>/mem:<databasename>
I've tried many combinations, but simply cannot get the remote connection to work. Is this feature working, can anyone give me the details of how they used this.
None of the solutions mentioned so far worked for me. Remote part just couldn't connect.
According to H2's official documentation:
To access an in-memory database from another process or from another computer, you need to start a TCP server in the same process as the in-memory database was created. The other processes then need to access the database over TCP/IP or TLS, using a database URL such as: jdbc:h2:tcp://localhost/mem:db1.
I marked the crucial part of the text in bold.
And I found a working solution at this guy's blog:
The first process is going to create the DB, with the following URL:
jdbc:h2:mem:db1
and it’s going to need to start a tcp Server:
org.h2.tools.Server server = org.h2.tools.Server.createTcpServer().start();
The other processes can then access your DB by using the following URL:
"jdbc:h2:tcp://localhost/mem:db1"
And that is it! Worked like a charm!
You might look at In-Memory Databases. For a network connection, you need a host and database name. It looks like you want one of these:
jdbc:h2:tcp://localhost/mem:db1
jdbc:h2:tcp://127.0.0.1/mem:db1
Complete examples may be found here, here and here; related examples are examined here.
Having just faced this problem I found I needed to append DB_CLOSE_DELAY=-1 to the JDBC URL for the tcp connection. So my URLs were:
In Memory : jdbc:h2:mem:dbname
TCP Connection : jdbc:h2:tcp://localhost:9092/dbname;DB_CLOSE_DELAY=-1
From the h2 docs:
By default, closing the last connection to a database closes the
database. For an in-memory database, this means the content is lost.
To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database
URL.
Not including DB_CLOSE_DELAY=-1 means that I cannot connect to the correct database via TCP. The connection is made, but it uses a different version to the one created in-memory (validated by using the IFEXISTS=true parameter)
In SpringBoot: https://www.baeldung.com/spring-boot-access-h2-database-multiple-apps
#Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseaServer() throws SQLException {
return Server.createTcpServer(
"-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}