Reputation: 4197
I have a need to put the database connection and close methods to AspectJ class. Currently my add method looks like below:
public void addBookDetails(String name, String author, String publisher, int year, int price){
Connection conn=null;
DBConnection DBConn=new DBConnection();
try {
conn=DBConnection.createConnection();
Statement statement=conn.createStatement();
System.out.println("INSERT INTO Books " + "VALUES ('"+name+"', '"+author+"', '"+publisher+"', '"+year+"', '"+price+"')");
statement.executeUpdate("INSERT INTO Books " + "VALUES ('"+name+"', '"+author+"', '"+publisher+"', '"+year+"', '"+price+"')");
DBConn.closeConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
How can I get this createConnection and closeConnection methods into as Aspect class? Because they dont belong to the scope of addBookDetails. Please advice. I dont understand how to use the "conn" object if I move this method. Because it will be needed for CreateStatement method in this class.
Upvotes: 0
Views: 1574
Reputation: 67297
Maybe you mean something like this?
Entity classes:
Here we have two classes, both with no-op addDetails(..)
methods. We expect the aspect to intercept these methods whenever they are executed and magically create/execute SQL statements for them.
package de.scrum_master.app;
public class Book {
public void addDetails(
String name, String author, String publisher, int year, int price
) {}
}
package de.scrum_master.app;
public class Person {
public void addDetails(
String firstName, String lastName, int yearOfBirth
) {}
}
Now let us assume we can derive the SQL table name from the class name by just appending a plural "s" to it. This will become important later in the aspect doing the SQL magic.
DB connection mock-up class:
This class does nothing special except for returning objects expected by the application. I am posting it here for the sake of making this example compileable and runnable.
package de.scrum_master.app;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class DBConnection {
public void closeConnection() {}
public static Connection createConnection() { return new Connection() {
@Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
@Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
@Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {}
@Override public void setTransactionIsolation(int level) throws SQLException {}
@Override public void setSchema(String schema) throws SQLException {}
@Override public Savepoint setSavepoint(String name) throws SQLException { return null; }
@Override public Savepoint setSavepoint() throws SQLException { return null; }
@Override public void setReadOnly(boolean readOnly) throws SQLException {}
@Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {}
@Override public void setHoldability(int holdability) throws SQLException {}
@Override public void setClientInfo(String name, String value) throws SQLClientInfoException {}
@Override public void setClientInfo(Properties properties) throws SQLClientInfoException {}
@Override public void setCatalog(String catalog) throws SQLException {}
@Override public void setAutoCommit(boolean autoCommit) throws SQLException {}
@Override public void rollback(Savepoint savepoint) throws SQLException {}
@Override public void rollback() throws SQLException {}
@Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {}
@Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql) throws SQLException { return null; }
@Override public String nativeSQL(String sql) throws SQLException { return null; }
@Override public boolean isValid(int timeout) throws SQLException { return false; }
@Override public boolean isReadOnly() throws SQLException { return false; }
@Override public boolean isClosed() throws SQLException { return false; }
@Override public SQLWarning getWarnings() throws SQLException { return null; }
@Override public Map<String, Class<?>> getTypeMap() throws SQLException { return null; }
@Override public int getTransactionIsolation() throws SQLException { return 0; }
@Override public String getSchema() throws SQLException { return null; }
@Override public int getNetworkTimeout() throws SQLException { return 0; }
@Override public DatabaseMetaData getMetaData() throws SQLException { return null; }
@Override public int getHoldability() throws SQLException { return 0; }
@Override public String getClientInfo(String name) throws SQLException { return null; }
@Override public Properties getClientInfo() throws SQLException { return null; }
@Override public String getCatalog() throws SQLException { return null; }
@Override public boolean getAutoCommit() throws SQLException { return false; }
@Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; }
@Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public Statement createStatement() throws SQLException { return new Statement() {
@Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
@Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
@Override public void setQueryTimeout(int seconds) throws SQLException {}
@Override public void setPoolable(boolean poolable) throws SQLException {}
@Override public void setMaxRows(int max) throws SQLException {}
@Override public void setMaxFieldSize(int max) throws SQLException {}
@Override public void setFetchSize(int rows) throws SQLException {}
@Override public void setFetchDirection(int direction) throws SQLException {}
@Override public void setEscapeProcessing(boolean enable) throws SQLException {}
@Override public void setCursorName(String name) throws SQLException {}
@Override public boolean isPoolable() throws SQLException { return false; }
@Override public boolean isClosed() throws SQLException { return false; }
@Override public boolean isCloseOnCompletion() throws SQLException { return false; }
@Override public SQLWarning getWarnings() throws SQLException { return null; }
@Override public int getUpdateCount() throws SQLException { return 0; }
@Override public int getResultSetType() throws SQLException { return 0; }
@Override public int getResultSetHoldability() throws SQLException { return 0; }
@Override public int getResultSetConcurrency() throws SQLException { return 0; }
@Override public ResultSet getResultSet() throws SQLException { return null; }
@Override public int getQueryTimeout() throws SQLException { return 0; }
@Override public boolean getMoreResults(int current) throws SQLException { return false; }
@Override public boolean getMoreResults() throws SQLException { return false; }
@Override public int getMaxRows() throws SQLException { return 0; }
@Override public int getMaxFieldSize() throws SQLException { return 0; }
@Override public ResultSet getGeneratedKeys() throws SQLException { return null; }
@Override public int getFetchSize() throws SQLException { return 0; }
@Override public int getFetchDirection() throws SQLException { return 0; }
@Override public Connection getConnection() throws SQLException { return null; }
@Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { return 0; }
@Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { return 0; }
@Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return 0; }
@Override public int executeUpdate(String sql) throws SQLException { return 0; }
@Override public ResultSet executeQuery(String sql) throws SQLException { return null; }
@Override public int[] executeBatch() throws SQLException { return null; }
@Override public boolean execute(String sql, String[] columnNames) throws SQLException { return false; }
@Override public boolean execute(String sql, int[] columnIndexes) throws SQLException { return false; }
@Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { return false; }
@Override public boolean execute(String sql) throws SQLException { return false; }
@Override public void closeOnCompletion() throws SQLException {}
@Override public void close() throws SQLException {}
@Override public void clearWarnings() throws SQLException {}
@Override public void clearBatch() throws SQLException {}
@Override public void cancel() throws SQLException {}
@Override public void addBatch(String sql) throws SQLException {}
};
}
@Override public SQLXML createSQLXML() throws SQLException { return null; }
@Override public NClob createNClob() throws SQLException { return null; }
@Override public Clob createClob() throws SQLException { return null; }
@Override public Blob createBlob() throws SQLException { return null; }
@Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; }
@Override public void commit() throws SQLException {}
@Override public void close() throws SQLException {}
@Override public void clearWarnings() throws SQLException {}
@Override public void abort(Executor executor) throws SQLException {}
};
}
}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new Book().addDetails("Gödel, Escher, Bach: An Eternal Golden Braid", "Douglas R. Hofstadter", "Basic Books", 1979, 990);
new Book().addDetails("Cryptonomicon", "Neal Stephenson", "Avon", 1999, 990);
new Person().addDetails("Albert", "Einstein", 1879);
new Person().addDetails("Werner", "Heisenberg", 1901);
}
}
Aspect:
The aspect has two helper methods taking care of
package de.scrum_master.aspect;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import de.scrum_master.app.DBConnection;
public aspect SqlUpdater {
void around() : execution(public void addDetails(..)) {
System.out.println(thisJoinPoint);
String sqlText = createSqlStatement(thisJoinPoint.getTarget().getClass(), thisJoinPoint.getArgs());
System.out.println(" " + sqlText);
connectToDbAndUpdate(sqlText);
proceed();
}
private static String createSqlStatement(Class<?> targetClass, Object[] args) {
StringBuilder sqlText = new StringBuilder("INSERT INTO ");
sqlText.append(targetClass.getSimpleName() + "s ").append("VALUES (");
int argSize = args == null ? 0 : args.length;
int i = 0;
for (Object arg : args) {
i++;
sqlText.append(arg instanceof String ? "'" : "").append(arg);
if (i < argSize)
sqlText.append(arg instanceof String ? "', " : ", ");
else
sqlText.append(arg instanceof String ? "'" : "");
}
sqlText.append(")");
return sqlText.toString();
}
private static void connectToDbAndUpdate(String sqlText) {
Connection sqlConnection = null;
DBConnection dbConnection = new DBConnection();
try {
sqlConnection = DBConnection.createConnection();
Statement sqlStatement = sqlConnection.createStatement();
sqlStatement.executeUpdate(sqlText);
dbConnection.closeConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Console output:
execution(void de.scrum_master.app.Book.addDetails(String, String, String, int, int))
INSERT INTO Books VALUES ('Gödel, Escher, Bach: An Eternal Golden Braid', 'Douglas R. Hofstadter', 'Basic Books', 1979, 990)
execution(void de.scrum_master.app.Book.addDetails(String, String, String, int, int))
INSERT INTO Books VALUES ('Cryptonomicon', 'Neal Stephenson', 'Avon', 1999, 990)
execution(void de.scrum_master.app.Person.addDetails(String, String, int))
INSERT INTO Persons VALUES ('Albert', 'Einstein', 1879)
execution(void de.scrum_master.app.Person.addDetails(String, String, int))
INSERT INTO Persons VALUES ('Werner', 'Heisenberg', 1901)
Feel free to ask follow-up questions if you do not understand the sample code.
Upvotes: 2