My problem is the following: I have to test an application which is written in Java Spring.
In real life the DB server will be an Oracle. There are some select where a DB link is used.
(For example: select * from country#isem_db; )
In test environment we use H2 database which doesn't know this syntax.(#)
My question is : Is this somehow possible to make this Oracle syntax acceptable for H2 ? Is some workaround exists for it without modifying the original source code?
Your Oracle code should not contain embedded database links. Database link names may change across environments, which makes your code brittle. Or you may need to switch to using a local copy (or materialized view).
The correct approach is to use synonyms. In Oracle you would create a synonym for the remote table:
create synonym isem_country for country#isem_db;
Obviously you need to change your Oracle code to reference the synonym name instead of the remote table.
This gives you the solution for running in H2, providing you're using a recent version which supports table synonyms. In H2 you would create a synonym with the same name but on the local table:
create synonym isem_country for country;
Related
I'm trying copy table from one database to another(On different machines), and using JDBC Template to execute query, but this request is specific to Oracle:
COPY FROM username1/passwd1#//192.168.3.17:1521/PROD_SERVICE to username2/passwd2#//192.168.4.17:1521/SANDBOX_SERVICE INSERT TABLE_C (*) USING (SELECT * FROM TABLE_C);
And I get error:
Caused by: java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
How can I use specific to Oracle syntax in JDBC?
Like some of the comments have already clarified, COPY is a sqlplus command, and it has been deprecated for a while. You cannot use it inside JAVA, because this command is not part of the SQL engine, it's just a kind of additional feature available only in sqlplus. It is still available, but only for backwards compatibility.
If you want to copy a table using Java, you need to understand first some things:
Java, or any external engine for that matter, can't connect at the same time to both databases. Either it connects to one or to the other.
You need to have a kind of bridge between both databases, so that your Java program is only acting as trigger.
Copying tables between databases is something related to the database, so you should think in using tools provided by your database engine. You have some options, like Datapump or RMAN, although I consider Datapump the best suitable for your scenario.
However, if you insist in using Java, first you need to have a database link between both databases. Then you can use Java to invoke an insert from one database to another.
https://docs.oracle.com/database/121/SQLRF/statements_5006.htm#SQLRF01205
If you don't want to depend on thsnames entries in the server, here an example of database links:
CREATE DATABASE LINK to_my_remote_user
CONNECT TO remote_user IDENTIFIED BY password
USING '(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=remote_server)(PORT=remote_port))
(CONNECT_DATA=(SERVICE_NAME=remote_service_name))
)';
Once you have the dblink created, then you can connect from java to the database where the link is available and copy the data to the remote database
INSERT INTO remote_user.remote_table#to_my_remote_user
select * from local_user.local_table ;
Important: Normally dblinks are not allowed on Production systems, because they increase security risks. Also remember that DDL operations over a database link require an extra step, such as using the procedure DBMS_UTILITY.EXEC_DDL_STATEMENT#dblink('create table ...);
Another option outside of Java is using SQL Developer copy feature. Although I only recommend it for small tables. If you want to use it with big tables, it will probably hang. You can read here an good example :
copy from one database to another using oracle sql developer - connection failed
Now that H2 1.4 is out of beta, I'd like to migrate my old 1.3.175 database to 1.4.195.
Background info:
In the docs, database upgrade does not mention 1.4 yet.
The roadmap still lists "Automatic migration from 1.3 databases to 1.4." as "planned change".
The current state of MVStore is still labeled as "experimental".
So, what's the recommended way to migrate?
Additional aspects/bonus questions:
Should I enable MVStore or stick with PageStore (pros/cons)? Which one delivers better performance (multithreading is not important for me), which one better stability, especially resilience against OutOfMemoryErrors?
A database created with 1.3.175 can be read and opened with 1.4.195 without any additional work. H2 will automatically detect that it is using the Page Store and treat it as such. There will be no problems with doing this.
The advantage to doing this is that while the MVStore was being developed, the Page Store continued to receive performance improvements and bug fixes. Consequently H2 with the Page Store has become an extremely stable database store.
There is as yet no automatic upgrade procedure for converting a database from using the Page Store to using the MVStore. If you do want to do this, you'll need to do it manually. With the latest H2 Jar, use H2's SCRIPT command to export SQL from your 1.3 database, then use RUNSCRIPT into a freshly created db with 1.4.195.
If your H2 JDBC URL doesn't explicitly specify ;mv_store=false, note that H2 will first look to see if a page store database already exists. If it doesn't then it will create an MVStore database. This will appear seamless to you, your app, and your users. The only superficial difference you'll notice is that the database file on disk has a different file extension.
Finally, a suggestion. If your customer databases are large, consider only using the page store. I'm a heavy user of H2. (My commercial product built on H2 has thousands of users who typically have databases many gigabytes in size.) I still use the page store for all my customers, even though I use the latest H2 Jar. There are still some performance issues with the MVStore that start to appear as databases get large. With time, I expect the cause of the problems to be identified and fixed.
#Steve McLeod's answer is on point. For completeness, here are the exact commands:
//Do a backup of current .h2.db file
//Connect to current DB with same URL as always
SCRIPT TO 'fileName'
//Rename the .h2.db to something else, possibly another backup
//Connect to database with same URL as before. The new MVStore engine will be chosen by default, and the .mv.db file will be created
RUNSCRIPT FROM 'fileName'
Documentation, H2 Grammar
Moreover, if you prefer using the H2 jar for this, refer to Thomas's answers (1 and 2). Concretely, the corresponding classes are org.h2.tools.Script and org.h2.tools.RunScript
To highlight another alternative for similar requests I would like to mention a tool which allows an automatized migration of an old H2 database into a new H2 database:
https://github.com/manticore-projects/H2MigrationTool
I am trying to understand "changing database without changing code". Currently working with micro services using springboot, java, thymeleaf and cloud foundry.
I have a spring boot application and attached a database as a service using cloud foundry.
My problem is I am seeing that the purpose of micro service is allowing the ease to change services without changing code.
Here is where I got stuck
In java I have a sql script, "select * from ORDER where Status = 'ACCEPTED';"
Images source
My database would be attached as a service on cloud foundry using CUPS
"jdbc:oracle:thin:username/password//host:port/servicename"
So let say I want to change this database to CUSTOMER table(take it as a different database). This will throw an error because CUSTOMER table will not have "select * from ORDER where Status = 'ACCEPTED';"
I've changed database, but wouldn't I still have to go back to my code and change the sql script?
My Attempt to resolve this issue
So instead of hard coding my sql script in java "select * from ORDER where Status = 'ACCEPTED';"
I created a system environment variable and set it as sqlScript with value of select * from ORDER where Status = 'ACCEPTED'
Then in java I called the env variable String sqlScript= System.getenv("sqlScript");
So now instead of going back into java to change sql script, user can change it through environment variables.
this is a very dirty method to go around my issue, what would be a better alternative?
I know my logic of understanding is really wrong. Please guide me to the right path.
I think the phrase 'changing database without changing code' doesn't mean that if you add/remove fields in DB you do not have to modify your codebase - it just doesn't make any sense.
What it really means is that you should use good database abstractions, so in case you need to change your database vendor from, let's say, MYSQL to OracleDB your Java code should stay the same. The only thing that may differ is some configurations.
A good example of it is ORM like Hibernate. You write your java code once, no matter what is the SQL Database that you are using underneath. To switch databases the only thing that you need to change is a dialect configuration property (In reality it's not that easy to do, but probably easier than if we were coupled to a one specific DB).
Hibernate gives you a good abstraction over SQL databases. Nowadays we have a new trend - having the abstraction over different DB families like SQL and NoSQL. So in the ideal world, your codebase should stay unchanged even if you want to change MySQL to MongoDB or even Neo4j. Spring Data probably is the most popular framework that tries to solve this problem. Another framework that I found recently is Kundera but I haven't used it so far.
So answering your question - you do not need to keep your SQL queries as system variables. All you need to do is to use proper abstractions in your language of choice.
In my opinion, it would be better to use something like Flyway or Liquibase, which are integrated really well in Spring Boot. You can find more information here.
I prefer Liquibase, since it uses a higher level format to describe your database migrations, allowing you to switch databases quite easily. This way, you can also use different databases per environment, for example:
HSQLDB during local development
MySQL in DEV and TEST
Oracle in Production
It's also possible to export your current database schema from an existing database to have an initial version in Flyway or Liquibase, this will give you a good baseline for your scripts.
I have a JDBC application that uses Apache Derby. How can I migrate my entire database system to use MySQL?
I have 3 Java programs that access the database
I have 3 tables and 2 views
I am using Netbeans. I have never used MySQL before and do not know where to begin. Is there nice integration with Java and MySQL in Netbeans? How can I get nice integration with NetBeans and MySQL?
All help is greatly appreciated!
Looks like this plugin would probably help you:
http://netbeans.org/kb/docs/ide/mysql.html
I found this tutorial on the Spring site, but I think it is only a partial solution.
Tutorial
In it they are relying on hibernate to drop and create the tables, and I really don't like that. You have to go through special coding to add static data. For example, if your app is tracking devices, you probably want a table of device_types. At least some o those device types will be in the db, as well as devices, users, etc.
What I intend to do, is to use Derby until I am somewhat stable. From it, I will get the database schema and create it in mysql. It seems that the DB look utility can be used for that. DB Look
As added security I intend to run my web app with a db user that does not have the ability to add or drop tables. Also it is possible to remove the permission to delete rows if you use the concept of making rows "inactive" So instead of deleting a no longer used device type, you set the "active" flag to F. So your device type query would look like:
select * from device_type where active = 'T'
Basically, I'm trying to selectively copy a table from one database to another. I have two different [Oracle] databases (e.g., running on different hosts) with the same schema. I'm interested in a efficient way to load Table A in DB1 with the result of running a select on Table A in DB2. I'm using JDBC, if that's relevant.
Use a database link, and use create table as select.
create database link other_db connect to remote_user identified by remote_passwd using remote_tnsname;
create table a as select * from a#other_db;
If the databases are from the same vendor they usually provide a native way to make a view
of a table in another database. in which case, a "select into" query will do it no problem
Oracle, for example, has the database link which works pretty well.
Outside of that you are going to have to make a connection to each database and read in
from one connection and write out to the other.
There are tools like Oracle's ODI that can do the legwork, but they all use the same
read in, write out model
You may not even need to move that data. Maybe you can just select across the database link.