For one of my poc, I would like to create a new PDB from java.
I am able to get cdb connection say,
Connection cdbConnection = DBUtils.getDBConnection(Constants.DB_CDB_NAME, Constants.DB_CDB_USER_NAME, Constants.DB_CDB_PASSWORD);
Now am trying to clone PDB3: CREATE PLUGGABLE DATABASE PDB5 FROM PDB3;
public static void createPluggableDB(Connection cdbConnection) {
try (Statement stmt = cdbConnection.createStatement();) {
stmt.executeUpdate("CREATE PLUGGABLE DATABASE PDB5 FROM PDB3;");
} catch (SQLException exception) {
// exception handling
}
}
When I execute this, am getting,
java.sql.SQLSyntaxErrorException: ORA-00922: missing or invalid option
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:446)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1052)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:537)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:255)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:610)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:213)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:37)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:887)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1136)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1754)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1709)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:300)
at com.xit.gtw.db.DBUtils.executeDBScripts(DBUtils.java:43)
at PluggableDBBuilder.createPluggableDB(PluggableDBBuilder.java:51)
at PluggableDBBuilder.main(PluggableDBBuilder.java:35)
Is it possible to create a PDB from java?
Thanks in advance!
You shouldn't have the semicolon in the string you pass to executeUpdate(); it's a statement separator not part of the statement. So remove that:
stmt.executeUpdate("CREATE PLUGGABLE DATABASE PDB5 FROM PDB3");
That applies to any statement you try to execute through JDBC (or, indeed, through many other mechanisms - including execute immediate).
Related
I tried a basic program to retrieve data from a database table into a java program. At the end of the compilation, when running the code an exception occurs. No error is shown in the console. It displays the exception message
import java.sql.*;
public class class1 {
public static void main(String args[]){
String url = "jdbc:mysql://localhost:3306//orders";
String username = "root";
String password = "Luxan#22";
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, username, password);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT CUST_NAME FROM CUSTOMERS");
System.out.println("List of Registered customers: ");
while(rs.next()){
System.out.println(rs.getString("cust_name"));
}
st.close();
con.close();
}
catch(Exception e){
System.out.println("An Exception error occured while processing JDBC programme");
}
}
}
Below is the output got in my console window
Fri Jan 17 19:34:24 IST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
An Exception error occured while processing JDBC programme
The problem is with your URL. Replace
"jdbc:mysql://localhost:3306//orders"
with
"jdbc:mysql://localhost:3306/orders"
Note that I have removed one / before orders.
Try to add ?useSSL=false to the end of the connection url.
It is difficult to see what went wrong, without knowing your table structure. But here is another way of writing your program. Maybe it helps you come closer to your goal:
public class Class1 {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver"); // this line is optional since Java 1.6 Normally for MySQL you shouldn't have to do this
// This is called "try-with-resources". It means that inside your "try" declaration you
// tell Java what things you want to open (here you wnat to open a connection)
// and it will automatically close any connection (on failure or success) for you
try (
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/orders", // before the database name there is only one /
"root", // the database user
"password"); // the password
Statement statement = connection.createStatement() // the same try-with resources can open the statement for your
) {
ResultSet rs = statement.executeQuery("SELECT CUST_NAME FROM CUSTOMERS");
while (rs.next()) {
System.out.println(rs.getString("cust_name"));
}
} catch (SQLException ex) {
Logger.getLogger(Class1.class).log(Level.SEVERE, null, ex); // this will properly log your SQLException. Don't be afraid, SQL error messages are scary and Java Exceptions are impressive. But they will tell you where the problem is
}
} catch (ClassNotFoundException ex) { // if you register your driver you need to catch the exception as well
Logger.getLogger(Class1.class).log(Level.SEVERE, null, ex);
}
}
}
You can read more about this example on MkYong.
I hope it helps you.
One more thing:
Class names start with a capital letter: Class1 instead of class1. Because variable names start with a small letter. Imagine you want to create an instance of a class called car. Then you would say car car = new car(); which is unreadable. Car car = new Car() however is clear :)
This piece of code uses an SQL query to return how many entries there are in a certain table.
public int countAmountOfEntries() {
int amount;
try (Connection conn = DriverManager.getConnection(Connection.JDBC_URL);
PreparedStatement query = conn.prepareStatement("SELECT COUNT(*) FROM Table")) {
try (ResultSet rs = query.executeQuery();) {
if (rs.next()) {
amount = rs.getInt("COUNT(*)");
}
}
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
return amount;
}
This should return any int other than 0. Initialising the variable to 0 will result in a NullPointerException being thrown as I'm using the return value of this to set the length of an array. Using the same code in another class returns the int it should return. I've tried using an alias for the COUNT(*) but to no avail.
Running the query directly into MySQL returns the int as well. I've tried removing the nested try (it was pretty much obsolete since I know it won't throw an exception if no one messes with my DB).
Did you register the JDBC driver before using it?
Class.forName("com.mysql.jdbc.Driver");
Is it required to provide an username/password upon connecting?
DriverManager.getConnection(url, user, pass);
Did you create a Connection class yourself which overwrites the Connection class returned upon opening the connection. The reason I ask this is because you retrieve the URL to connect to using Connection.JDBC_URL which is (as far as I know) not in the Connection class.
Is there already a connection opened and your database only allows 1 open connection?
Note: do not forget to close the resultset, statement, and connection before returning:
rs.close();
query.close();
conn.close();
Besides that, restructure your function because a try without catch does not help at all.
This looks really weird:
amount = rs.getInt("COUNT(*)");
Try this instead
amount = rs.getInt(1);
I want to insert every filename of my local drive into a mysql database.
When I execute this code, it start perfectly.
Code that reads the directory for filenames:
public void main(String[] args)throws IOException {
JOptionPane.showMessageDialog(null, "IT MAY TAKE SOMETIME TO LOAD \n PLEASE WAIT FOR CLOSING POPUP!!");
String s="D:\\";
Path startingDir = Paths.get(s);
String pattern="*";
Finder finder = new Finder(pattern);
Files.walkFileTree(startingDir, finder);
JOptionPane.showMessageDialog(null,"close\n NOW PLEASE CLICK\nSEARCH MY FILE! BUTTON");
This is the code to insert the results into the database:
public void find(Path file) {
Path name = file.getFileName();
String st = file.toString();
if (name != null && matcher.matches(name)) {
try {
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost/login","root","");
conn.createStatement();
String query =" INSERT INTO `search`(`path`) VALUES (?)";
PreparedStatement pst=conn.prepareStatement(query);
pst.setString(1,st );
pst.execute();
//myst.executeUpdate(query);
} catch (SQLException e) {
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null, e);
}
After some time, the scripts stops with this exception
com.mysql.jdbc.exception.jdbc4.MYSQLNonTransientConnectionException:
Data source rejected establishment of connection,
message from server:"Too Many connections"
Is there any way to solve this problem?
For every insert you create a new connection. If you keep doing this they build up and eventually you run out of connections to the database. This limit could be quite small e.g. 20.
Instead you can either
close the resources you have used. This means closing the PreparedStatement and the Connection
or more efficiently, create one Connection and one PrepareStatement ever and reuse it. The saves having to create and clean up resources which can be expensive (unless the driver does this recycling for you)
the easy fix would be to close the connection after you execute the query.
pst.close();
conn.close();
this should get the job done.
But it'd be better to reuse the connection.
While running the following code
public class Temp {
public static void main(String args[]) {
Connection con; // The connection to the database.
// The following code can throw errors, so they must be caught.
try{
// First, tell Java what driver to use and where to find it.
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// Next, create a connection to your data source.
// Specify that you are using the ODBC-JDBC Bridge.
// And specify the data source from ODBC.
con = DriverManager.getConnection("jdbc:odbc:Temp");
// Create an SQL statement.
Statement stmt = con.createStatement();
// Execute some SQL to create a table in your database.
// If the table already exists, an exception is thrown!
stmt.executeUpdate("CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
"SALES INTEGER, TOTAL INTEGER)");
}
// Catch any exceptions that are thrown.
catch(ClassNotFoundException e){
System.out.println(e.toString());
}
catch(SQLException e){
System.out.println(e.toString());
}
}
}
i got the error as
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Cannot modify the design of table 'COFFEES'. It is in a read-only database.
please help
Make sure that you have write access to the database/file with your current user.
Check the advanced options in the ODBC DSN and make sure ReadOnly is set to 0.
You need to add "ReadOnly=False;" to your connection string
try deleting the table explicitly and run again.
In the context of a java application using SQLIte to persist data I am using the Zentus JDBC driver. Thus I am using the java.sql package to acces my database.
I am facing some strange (in a an environment with several Connection objects on the same database) issues and I am pretty sure my problems come from non closed ResultSet.
Is there any tool or technique allowing me to spot where to look in my source code to find these non closed objects ?
Edit May be using AspectJ ??
It seems like an aspect may be helpful.
How about wrapping the methods which return a result set in an aspect. Something like:
execution(public java.sql.ResultSet+ java.sql.Statement+.*(..))
Another aspect can monitor the close method on ResultSets. Perhaps:
execution(public * java.sql.ResultSet.close())
The first aspect would, on the return of every ResultSet, create a new Exception object and store it in a static Map somewhere using the hash of the ResultSet as the key. The second aspect, on the closing of the result set, would remove the Exception from the Map using the same hashcode as a key. At any time, the map should have one exception instance for every open ResultSet. From the exception you can obtain a stack trace to see where the ResultSet was opened.
You could perhaps store a larger object which includes an exception and some other contextual information; time that the ResultSet was created, etc.
A practical suggestion is to add some debug code and "log" creation and closing of resultsets to a csv file. Later on you could examine this file and check, if there's a "close" entry for each "create".
So, assuming you have a utility class with static methods that allows writing Strings to a file, you can do it like this:
ResultSet rs = stmt.executeQuery(query);
Util.writeln(rs.hashcode() + ";create"); // add this line whenever a
// new ResultSet is created
and
rs.close();
Util.writeln(rs.hashcode() + ";closed"); // add this line whenever a
// ResultSet is closed
Open the csv file with Excel or any other spread sheet program, sort the table and look if result sets are not closed. If this is the case, add more debug information to clearly identify the open sets.
BTW - Wrapping the interfaces (like JAMon) is pretty easy, if you have eclipse or something else, its coded in less then 15 Minutes. You'd need to wrap Connection, Statement (and PreparedStatement?) and ResultSet, the ResultSet wrapper could be instrumented to track and monitor creation and closing of result sets:
public MonitoredConnection implements Connection {
Connection wrappedConnection = null;
public MonitoredConnection(Connection wrappedConnection) {
this.wrappedConnection = wrappedConnection;
}
// ... implement interface methods and delegate to the wrappedConnection
#Override
public Statement createStatement() {
// we need MonitoredStatements because later we want MonitoredResultSets
return new MonitoredStatement(wrappedConnection.createStatemet());
}
// ...
}
The same for MonitoredStatement and MonitoredResultSet (MonitoredStatement will return wrapped ResultSets):
public MonitoredStatement implements Statement {
private Statement wrappedStatement = null;
#Override
public ResultSet executeQuery(String sql) throws SQLException
MonitoredResultSet rs = wrappedStatement.executeQuery(sql);
ResultSetMonitor.create(rs.getWrappedResultSet()); // some static utility class/method
return rs;
}
// ...
}
and
public MonitoredResultSet implements ResultSet {
private ResultSet wrappedResultSet;
#Override
public void close() {
wrappedResultSet.close();
ResultSetMonitor.close(wrappedResultSet); // some static utility class/method
}
// ...
}
At the end, you should only need to modify a single line in your code:
Connection con = DriverManager.getConnection(ur);
to
Connection con = new MonitoredConnection(DriverManager.getConnection(ur));
A Google Search pointed me directly to JAMon. It allows you to also monitor JDBC connections and cursors.
Personally, I would check the code and make sure that all Statement, PreparedStatement and ResultSet are closed when not needed. Even when using Connection Pooling, only JDBC Connection are returned into the pool and statements and ResultSet are closed.
This example shows how I achieve closing ResultSet and PreparedStatement in the finally close (for guarantee):
PreparedStatement ps = null;
ResultSet rs = null;
UserRequest request = null;
try {
ps = getConnection().prepareStatement(SQL_RETRIEVE);
ps.setLong(1, id);
rs = ps.executeQuery();
if (rs != null && rs.next()) {
request = mapEntity(rs);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
throw new DAOException(e);
} finally {
try {
close(rs, ps);
} catch (SQLException e) {
// TODO Auto-generated catch block
logger.error("Error closing statement or resultset.", e);
}
}
That's my 2 cents worth...hope it helps you.
It should be relatively simple to instrument your code with AOP of your choice. I was using AspectWerkz number of years ago to do load-time weaving of web app and collecting performance related statistics. Also if you're using IOC framework, such as Spring it's very easy to wrap your DataSources and trace calls to getConnection() etc.