I'm trying to write a class that implements DataSource. This seems simple enough, but the examples I'm seeing for Oracle all declare the class like this:
public class ConnectionPoolingBean implements SessionBean {
....
}
I would expect to see something more like this:
public class MyDataSource implements DataSource {
....
}
Also, I don't understand how the connection is actually working. The getConnection() method only takes the arguments for username and password. So how am I connecting to my database?
Ultimately, what I need to understand is how do I connect to my database and return a result set from a query using DataSource. I just don't see any clear examples of how write a class to use this on my WebApp.
Here's what I've been reading from, which is now just confusing me.
https://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html
http://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html
Use any connection pool for your use case.If you are using app server you can use app server connection pool or use opensource dbcp connection pool mechanism.
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
Example
import org.apache.commons.dbcp2.BasicDataSource;
public class DataBaseUtility
{
private static BasicDataSource dataSource;
private static BasicDataSource getDataSource()
{
if (dataSource == null)
{
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost/test");
ds.setUsername("root");
ds.setPassword("password");
ds.setMinIdle(5);
ds.setMaxIdle(10);
ds.setMaxOpenPreparedStatements(100);
dataSource = ds;
}
return dataSource;
}
public static void main(String[] args) throws SQLException
{
try (BasicDataSource dataSource = DataBaseUtility.getDataSource();
Connection connection = dataSource.getConnection();
PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM account");)
{
System.out.println("The Connection Object is of Class: "+connection.getClass());
try (ResultSet resultSet = pstmt.executeQuery();)
{
while (resultSet.next())
{
System.out.println(resultSet.getString(1) + "," + resultSet.getString(2) + "," + resultSet.getString(3));
}
}
catch (Exception e)
{
connection.rollback();
e.printStackTrace();
}
}
}
}
Related
How to create a Firebird connection using Spring Boot to make views in SQL using the Firebird database? I have no idea how to build this.
try {
Class.forName("org.firebirdsql.jdbc.FBDriver");
Connection con= DriverManager.getConnection("jdbc:firebirdsql:localhost/3050:C:/DB/DASHBOARD.FDB","sysdba","masterkey");
Statement stm= con.createStatement();
ResultSet res= stm.executeQuery("SELECT * FROM TBLEMPLOYEE");
while (res.next()) {
System.out.println("DASHBOARD LASTNAME:"
+ res.getString("LASTNAME"));
}
} catch (Exception e) {
System.out.println(e);
}
I tried to make a connection string, but without success because Spring doesn't recognize it.
Take the following steps:
Go to https://start.spring.io/
Configure it with Maven (or Gradle if you prefer that)
Enter the desired coordinates for your project
Add dependency JDBC
Click Generate and unpack the zip to a location on your computer
Open the project in you favorite IDE
In the pom.xml, in the dependencies section add Jaybird (the Firebird JDBC driver):
<dependency>
<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird</artifactId>
</dependency>
Or, if you used Gradle, add to the dependencies section of build.gradle:
runtimeOnly 'org.firebirdsql.jdbc:jaybird'
In src/main/resources/application.properties add:
spring.datasource.url=jdbc:firebirdsql://localhost/employee
spring.datasource.username=sysdba
spring.datasource.password=masterkey
In the package generated by the initializr (default com.example.demo), add a new class SimpleRunner:
package com.example.demo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
#Component
public class SimpleRunner implements CommandLineRunner {
private final DataSource dataSource;
public SimpleRunner(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public void run(String... args) throws Exception {
try (var connection = dataSource.getConnection();
var stmt = connection.createStatement();
var rs = stmt.executeQuery("select first_name, last_name from employee")) {
while (rs.next()) {
System.out.printf("%s %s%n",
rs.getString("first_name"), rs.getString("last_name"));
}
}
}
}
This very basic application will connect to the Firebird example database employee, and print out the first and last names of the employees in the employee table.
I have the following code in a simple spring boot app...
#Bean
public DataSource getDatasource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(driver);
ds.setUsername(username);
ds.setUrl(url);
ds.setPassword(password);
return ds;
}
This worked great but I wanted connection pooling so I changed to...
#Bean
public DataSource getDatasource(){
try{
OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource();
ds.setDriverType("thin");
ds.setUser(username);
ds.setNetworkProtocol("tcp");
ds.setPassword(password);
ds.setDatabaseName(dbName);
ds.setServerName(serverName);
return ds;
} catch (SQLException throwables) {
logger.error(throwables);
System.exit(-1);
}
return null;
}
But from the documentation it looks like getConnection just returns a native connection and I need to configure Spring to call getPooledConnection instead.
Is there another bean I can create or some other way I can do this?
It looks like if you are doing this with Oracle you are supposed to use a library called UCP or Universal Connection Pooling...
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ucp</artifactId>
<version>21.1.0.0</version>
</dependency>
Then I use that to create the datasource like...
PoolDataSource ds = PoolDataSourceFactory.getPoolDataSource();
ds.setConnectionFactoryClassName(OracleDataSource.class.getName());
ds.setURL(url);
ds.setUser(username);
ds.setPassword(password);
ds.setInitialPoolSize(1);
ds.setMinPoolSize(1);
ds.setMaxPoolSize(10);
return ds;
I am finishing my testing to make sure it is working as expected.
For using Universal Connection Pool (UCP), you do need ucp.jar in the classpath. Refer to UCPSample.java for an example.
In my Java application I have such code:
private static OracleDataSource oracleDatasource;
public static OracleConnection getConnection() throws SQLException
{
final OracleConnection conn = (OracleConnection) oracleDatasource.getConnection("user", "password");
return conn;
}
I would like to write equivalent of such function in Postgres JDBC. I know that I could use this line
private static PGSimpleDataSource postgresDatasource;
to define data source. But how can I define and return connection variable like it was in Oracle?
I keep randomly getting this error every once in a while: "java.sql.SQLSyntaxErrorException: User '{key}' has exceeded the 'max_user_connections' resource (current value: 10)".
I have tried googling help for this, but all I can find is:
"increase the max connections limit" (which can't be done in free clearDB)
"adjust maxActive amount" or "release old connections" (both of which I can't find how to do it in Spring Boot)
Here's what my code looks like:
// application.properties
# Connect to heroku ClearDB MySql database
spring.datasource.url=jdbc:mysql://{heroku_url}?reconnect=true
spring.datasource.username={user}
spring.datasource.password={password}
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update
#MySQL DIALECT
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.open-in-view=false
server.port=8080
#Configuration
public class DatabaseConfig {
#Value("${spring.datasource.url}")
private String dbUrl;
#Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
return new HikariDataSource(config);
}
}
EDIT 1: I was following PauMAVA's instructions as best as I could and I came up with this code, which for some reason fails:
#Configuration
public class DatabaseConfig {
#Value("${spring.datasource.url}")
private String dbUrl;
public static DataSource ds;
#Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
DataSource ds = new HikariDataSource(config);
DatabaseConfig.ds = ds;
return ds;
}
}
// Main class
public static void main(String[] args) {
SpringApplication.run(BloggerApplication.class, args);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
DataSource ds = DatabaseConfig.ds;
if (ds != null) {
try {
ds.getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}, "Shutdown-thread"));
}
Whenever you create a connection object in you code, it is advisable to close the same in finally block. This way the number of connections do not get exhausted.
Hope this helps!
You should close the DataSource on application termination so that no unused connections remain open.
public void close(DataSource ds) {
if(ds != null) {
ds.close();
}
}
But do this only on program termination as stated here.
To use the data source later (on closing) you can register the DataSource as a Field in your class:
private DataSource ds;
#Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
DataSource ds = new HikariDataSource(config);
this.ds = ds;
return ds;
}
If you are going to have more than one data source you can make a List based approach:
private List<DataSource> activeDataSources = new ArrayList<>();
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
DataSource ds = new HikariDataSource(config);
this.activeDataSources.add(ds);
return ds;
}
public void closeAllDataSources() {
for(DataSource ds: this.activeDataSources) {
if(ds != null) {
ds.close();
}
}
this.activeDataSources = new ArrayList<>();
}
To execute a function on program close refer to this.
I worked on mysql server and connected my java applications successfully. And now I changed to MariaDB. How to connect with MariaDB server using java?
How this should be changed?
public class DBConnection {
private Connection connection;
private static DBConnection dBConnection;
public DBConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "root", "mysql");
}
public static DBConnection getDBConnection() throws ClassNotFoundException, SQLException {
if (dBConnection == null) {
dBConnection = new DBConnection();
}
return dBConnection;
}
public Connection getConnection() {
return connection;
}
}
Minor changes for MariaDB are as follows: Use the MariaDB Connector/J with the following Driver class:
org.mariadb.jdbc.Driver
For DB Connection use the following structure:
jdbc:(mysql|mariadb)://host:port/[database]
Therefore, your code as above would only require the change for
Class.forName("org.mariadb.jdbc.Driver");
and the rest would work well since MySQL and MariaDB clients are compatible.After all, MariaDB is an enhanced, drop-in replacement for MySQL.
More information about connecting to MariaDB using the Java Connector can be accessed from MariaDB Knowledge Base (MariaDB Connector/J