Skip to content

Commit 7e0b967

Browse files
committed
added Oracle connection
1 parent e1ab140 commit 7e0b967

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package io.github.kdesp73.databridge.connections;
2+
3+
import java.sql.*;
4+
import io.github.kdesp73.databridge.helpers.Again;
5+
import io.github.kdesp73.databridge.helpers.Config;
6+
import io.github.kdesp73.databridge.helpers.SQLogger;
7+
8+
/**
9+
* The {@code OracleConnection} class implements the {@link DatabaseConnection} interface
10+
* for connecting to and interacting with an Oracle database.
11+
* <p>
12+
* This class provides methods to establish a connection, execute SQL queries (SELECT, UPDATE),
13+
* call Oracle functions and procedures, and close the connection. It also supports calling functions
14+
* that return values or tables and handles retries for failed operations using the {@link Again} helper.
15+
*
16+
* <p>
17+
* This class also logs errors related to database operations using the {@link SQLogger}.
18+
*/
19+
public class OracleConnection implements DatabaseConnection {
20+
21+
private Connection connection;
22+
23+
/**
24+
* Returns the underlying {@link Connection} object for the Oracle database.
25+
*
26+
* @return the {@link Connection} instance for the database connection.
27+
*/
28+
@Override
29+
public Connection get() {
30+
return this.connection;
31+
}
32+
33+
/**
34+
* Establishes a connection to the Oracle database.
35+
*
36+
* @param url the database URL in the format {@code jdbc:oracle:thin:@host:port:service}.
37+
* @param username the username for database access.
38+
* @param password the password for database access.
39+
* @throws SQLException if the connection to the database fails.
40+
*/
41+
@Override
42+
public void connect(String url, String username, String password) throws SQLException {
43+
if (!url.startsWith("jdbc:oracle:thin:@")) {
44+
url = "jdbc:oracle:thin:@" + url;
45+
}
46+
try {
47+
Class.forName("oracle.jdbc.driver.OracleDriver");
48+
connection = DriverManager.getConnection(url, username, password);
49+
} catch (ClassNotFoundException e) {
50+
SQLogger.getLogger(SQLogger.LogLevel.ERRO, SQLogger.LogType.FILE).log(Config.getInstance().getLogLevel(),
51+
"Oracle Connection Failed", e);
52+
throw new SQLException("Oracle driver not found. Check https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc11 to get the latest version", e);
53+
}
54+
}
55+
56+
/**
57+
* Executes an UPDATE SQL query (INSERT, UPDATE, DELETE) on the Oracle database.
58+
*
59+
* @param query the SQL query string to execute.
60+
* @return the number of rows affected by the query.
61+
* @throws SQLException if a database access error occurs or if the query is invalid.
62+
*/
63+
@Override
64+
public int executeUpdate(String query) throws SQLException {
65+
return Again.retryWithDelay(() -> {
66+
try (PreparedStatement statement = connection.prepareStatement(query)) {
67+
return statement.executeUpdate();
68+
}
69+
}, Again.retries(), Again.delay());
70+
}
71+
72+
/**
73+
* Executes a SELECT SQL query and returns the result as a {@link ResultSet}.
74+
*
75+
* @param query the SQL SELECT query string to execute.
76+
* @return a {@link ResultSet} containing the result of the query.
77+
* @throws SQLException if a database access error occurs or if the query is invalid.
78+
*/
79+
@Override
80+
public ResultSet executeQuery(String query) throws SQLException {
81+
return Again.retryWithDelay(() -> {
82+
PreparedStatement statement = connection.prepareStatement(query);
83+
return statement.executeQuery();
84+
}, Again.retries(), Again.delay());
85+
}
86+
87+
/**
88+
* Executes a DDL SQL query (e.g., CREATE, ALTER, DROP) on the Oracle database.
89+
*
90+
* @param query the SQL DDL query string to execute.
91+
* @return {@code true} if the query executed successfully, {@code false} otherwise.
92+
* @throws SQLException if a database access error occurs or if the query is invalid.
93+
*/
94+
@Override
95+
public boolean execute(String query) throws SQLException {
96+
return Again.retryWithDelay(() -> {
97+
try (Statement statement = connection.createStatement()) {
98+
return statement.execute(query);
99+
}
100+
}, Again.retries(), Again.delay());
101+
}
102+
103+
/**
104+
* Closes the database connection, releasing any resources.
105+
*
106+
* @throws SQLException if an error occurs while closing the connection.
107+
*/
108+
@Override
109+
public void close() throws SQLException {
110+
if (connection != null) {
111+
connection.close();
112+
}
113+
}
114+
115+
/**
116+
* Calls a Oracle function that returns a table of records.
117+
* <p>
118+
* This method prepares and executes a SQL query to call the specified Oracle function,
119+
* returning the result as a {@link ResultSet}.
120+
*
121+
* @param functionName the name of the Oracle function to call.
122+
* @param params the parameters to pass to the function.
123+
* @return a {@link ResultSet} containing the results of the function call. The caller is responsible
124+
* for closing the {@link ResultSet}.
125+
* @throws SQLException if an error occurs during the function call.
126+
*/
127+
public ResultSet callFunction(String functionName, Object... params) throws SQLException {
128+
validateConnection();
129+
StringBuilder sql = new StringBuilder("SELECT * FROM ").append(functionName).append("(");
130+
for (int i = 0; i < params.length; i++) {
131+
sql.append("?");
132+
if (i < params.length - 1) {
133+
sql.append(", ");
134+
}
135+
}
136+
sql.append(")");
137+
138+
try {
139+
PreparedStatement stmt = connection.prepareStatement(sql.toString());
140+
for (int i = 0; i < params.length; i++) {
141+
stmt.setObject(i + 1, params[i]);
142+
}
143+
return stmt.executeQuery();
144+
} catch (SQLException e) {
145+
SQLogger.getLogger(SQLogger.LogLevel.ERRO, SQLogger.LogType.FILE)
146+
.log(Config.getInstance().getLogLevel(), "Error calling function " + functionName, e);
147+
throw new SQLException(e);
148+
}
149+
}
150+
151+
/**
152+
* Calls a Oracle function that returns a single value.
153+
* <p>
154+
* This method prepares and executes a SQL call to the specified Oracle function, returning
155+
* the value of the result.
156+
*
157+
* @param functionName the name of the Oracle function to call.
158+
* @param returnType the JDBC return type of the function result.
159+
* @param params the parameters to pass to the function.
160+
* @return the result of the function call.
161+
* @throws SQLException if an error occurs during the function call.
162+
*/
163+
public Object callFunctionValue(String functionName, int returnType, Object... params) throws SQLException {
164+
validateConnection();
165+
StringBuilder sql = new StringBuilder("{ ? = call ").append(functionName).append("(");
166+
for (int i = 0; i < params.length; i++) {
167+
sql.append("?");
168+
if (i < params.length - 1) {
169+
sql.append(", ");
170+
}
171+
}
172+
sql.append(") }");
173+
174+
try (CallableStatement stmt = this.connection.prepareCall(sql.toString())) {
175+
stmt.registerOutParameter(1, returnType);
176+
for (int i = 0; i < params.length; i++) {
177+
stmt.setObject(i + 2, params[i]);
178+
}
179+
stmt.execute();
180+
return stmt.getObject(1);
181+
} catch (SQLException e) {
182+
SQLogger.getLogger(SQLogger.LogLevel.ERRO, SQLogger.LogType.FILE)
183+
.log(Config.getInstance().getLogLevel(), "Error calling function " + functionName, e);
184+
throw new SQLException(e);
185+
}
186+
}
187+
188+
/**
189+
* Calls a Oracle stored procedure.
190+
* <p>
191+
* This method prepares and executes a SQL call to the specified stored procedure.
192+
*
193+
* @param procedureName the name of the Oracle procedure to call.
194+
* @param params the parameters to pass to the procedure.
195+
* @throws SQLException if an error occurs during the procedure call.
196+
*/
197+
public void callProcedure(String procedureName, Object... params) throws SQLException {
198+
validateConnection();
199+
StringBuilder sql = new StringBuilder("CALL ").append(procedureName).append("(");
200+
for (int i = 0; i < params.length; i++) {
201+
sql.append("?");
202+
if (i < params.length - 1) {
203+
sql.append(", ");
204+
}
205+
}
206+
sql.append(")");
207+
208+
try (CallableStatement stmt = connection.prepareCall(sql.toString())) {
209+
for (int i = 0; i < params.length; i++) {
210+
stmt.setObject(i + 1, params[i]);
211+
}
212+
stmt.execute();
213+
} catch (SQLException e) {
214+
SQLogger.getLogger(SQLogger.LogLevel.ERRO, SQLogger.LogType.FILE)
215+
.log(Config.getInstance().getLogLevel(), "Error calling procedure " + procedureName, e);
216+
throw new SQLException(e);
217+
}
218+
}
219+
220+
/**
221+
* Validates whether the database connection is active.
222+
*
223+
* @throws SQLException if the connection is not active or established.
224+
*/
225+
private void validateConnection() {
226+
try {
227+
if (connection == null || connection.isClosed()) {
228+
throw new SQLException("No active database connection.");
229+
}
230+
} catch (SQLException e) {
231+
throw new RuntimeException("Connection validation failed", e);
232+
}
233+
}
234+
}

0 commit comments

Comments
 (0)