SQL: 4 classes must reference one central class which provides database access - mysql

I want to make several entries into a MySQL database. Because Some of the tables reference others via foreign key I have to get back the inserted ID to inject them in my next statements.
I have 4 classes:
LodgerFormTest
RentForm
RentObject
House
and the class which inserts the MySQL statements into the db: sql_statements
When I want to send a SQL statement I am getting a nullPointer Exception!
The Action listener of the House-class (this is the first sql-statement I have to send) looks like this:
saveButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("saveButton");
// sql_statements statements = new sql_statements();
sql_statements.performHouse(strasse.getText(), plz.getText(), ort.getText());
mainmenu.create();
rentnerFrame.dispose();
}
});
all methods and variables I am using in sql_statements are static! Therefore I am not instantiating an object.
here is the method "performHouse" in sql_statements
public static void performHouse(String strasse, String plz, String ort) {
String sql = "insert into haus(strasse, plz, ort) values (?,?,?)";
System.out.println(sql);
try{
ps = connect.prepareStatement(sql, ps.RETURN_GENERATED_KEYS);
ps.setString(1, strasse);
ps.setString(2, plz);
ps.setString(3, ort);
ps.execute();
rs = ps.getGeneratedKeys();
if(rs != null && rs.next()) {
// Retrieve the auto generated key(s).
key_idhaus = rs.getLong(1);
System.out.println("idhaus: " + key_idhaus);
}
}catch(Exception ex){
System.out.println(ex);
}
} // close performHouse-methode
I cant debug because I get a "Source not found." error in the debug view.
Can anybody help please?

okay I just wanted to finish the task so I implemented a solution which surely is all but not OO:
I implemented redundant code into all of the 4 classes and every class implements their own sql statements. quick and dirty ;)

Related

How to get inserted id using Spring Jdbctemplate.update(String sql, obj...args)

I'm using Jdbctemplate and I need the inserted id of a query.
I read that I have to build a particular PreparedStatement and use GeneratedKeyHolder object.
The problem is that in my application all inserts method uses this JdbcTemplate update method:
getJdbcTemplate().update(SQL_INSERT,param1,param2,param3,...);
Is there another way to get the inserted id without refactoring all daos?
Looking at the documentation for NamedParameterJdbcTemplate and JdbcTemplate You have two choices:
use NamedParameterJdbcTemplate's update method.
use JdbcTemplate's update method.
There are also some other methods available which will populate the keys to the given GeneratedKeyHolder, it's up to you which one suits your needs.
EDIT
For e.g. using JdbcTemplate:
GeneratedKeyHolder holder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement statement = con.prepareStatement("INSERT INTO SOME_TABLE(NAME, VALUE) VALUES (?, ?) ", Statement.RETURN_GENERATED_KEYS);
statement.setString(1, "SomeName");
statement.setString(2, "SomeValue");
return statement;
}
}, holder);
long primaryKey = holder.getKey().longValue();
This does not work for PostgreSQL, the holder returns all the attributes. Here is a link to the solution in PostgreSQL Spring: How to use KeyHolder with PostgreSQL

Ebean calling stored procedure and converting ResultSet to Model

I'm working in report module, in order to do that I'm creating different stored procedures. I create the procedure with in parameters and then create a class to map the row (resultSet)
I think that's the best way to work arround performance and clarity.(what do you think about that?)
I'm using play framework and ebean orm (2.7.7)
I'm calling the store procedure and getting the resultSet, but I would like to use ebean in order to cast automaticly the row to model... other option is take the row-cell and cast it in a property but I'm trying to avoid it.
This is the current approach
Is this the best way to call an stored procedure?
Transaction tx = Ebean.beginTransaction();
String sql = "{CALL report(?, ?, ?, ?, ?, ?)}";
CallableStatement callableStatement = null;
try {
Connection dbConnection = tx.getConnection();
callableStatement = dbConnection.prepareCall(sql);
callableStatement.setInt(1, 3);
callableStatement.setInt(2, 5);
callableStatement.setInt(3, 2013);
callableStatement.setInt(4, 1);
callableStatement.setInt(5, 2014);
callableStatement.setInt(6, 5);
ResultSet rs = callableStatement.executeQuery(sql);
while (rs.next()) {
//HOW TO CONVER row -> model ?
}
Ebean.commitTransaction();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I've discarded RawSQL and Query because received an error
RuntimeException: Error parsing sql, can not find SELECT keyword in: xxxxx
Also I found other option... using CallableSql
String sql = "{call sp_order_mod(?,?)}";
CallableSql cs = Ebean.createCallableSql(sql);
cs.setParameter(1, "turbo");
cs.registerOut(2, Types.INTEGER);
Ebean.execute(cs);
// read the out parameter
Integer returnValue = (Integer) cs.getObject(2);
but in this case I need to return a ResultSet not simply parameter.
I'm going to share my own solution.
I get a class called ResultSetUtils.(you can google it some implementation)
I added a generic method in order to return a typed list from resultset
public static <T> List<T> populateInList(Class<T> c, final ResultSet rs) {
List<T> listTyped = new ArrayList<T>();
try {
if (rs != null) {
while (rs.next()) {
T o = c.newInstance();
// MAGIC LINE
populate(o, rs);
listTyped.add(o);
}
rs.close();
}
} catch (final Exception e) {
// TODO Auto-generated catch block
System.err.println(e.getMessage());
}
return listTyped;
}
This class to do the population use org.apache.commons.beanutils package
BeanUtils.populate(bean, propertiesRealName);
Using
private static void callingProcedureTest() {
Logger.debug("Init callingProcedureTest");
Transaction tx = Ebean.beginTransaction();
// String sql = "{CALL sp_report_test(3, 5, 2013, 1, 2014, 5)}";
String sql = "CALL sp_report_test(?, ?, ?, ?, ?, ?);";
try {
Connection dbConnection = tx.getConnection();
CallableStatement callableStatement = dbConnection.prepareCall(sql);
callableStatement.setInt(1, 3);
callableStatement.setInt(2, 5);
callableStatement.setInt(3, 2013);
callableStatement.setInt(4, 1);
callableStatement.setInt(5, 2014);
callableStatement.setInt(6, 5);
Logger.debug("SQL > " + sql);
ResultSet rs = callableStatement.executeQuery();
Class<ReportTestResult> c = ReportTestResult.class;
//************** MAGIC LINE, converting ResultSet to Model
List<ReportTestResult> listResult = ResultSetUtils.populateInList(c, rs);
for (ReportTestResult item : listResult) {
Logger.debug("item.firstName> " + item.firstName);
Logger.debug("item.lastName > " + item.lastName);
Logger.debug("item.year > " + item.year);
}
Ebean.commitTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
Ebean.endTransaction();
}
}
Plus about architecture and implementation
For each report I'm going to create:
a Result class (eg ReportTestResult)
intention: represent a row of report | simple DTO
a Param class (eg ReportTestParam),
intention: represent the parameters (inputs / ouputs), filters of the report
This class should implements
public interface ReportParam {
public int countParameteres();
public void setParametersInCallableStatement(CallableStatement callableStatement) throws SQLException;
}
a Report class (eg ReportTestReport) this class should extends ReportBase
intention: Knows the stored procedure's name, parameters and dto result
public class ReportTestReport extends ReportBase<ReportTestResult, ReportTestParam> {
#Override
protected String getProcedureName() {
return STORED_NAME;
}
}
many Adapters...
Each report could displayed in different charts, In this case I'm using HighCharts. Order to arrange it, I'm creating different adapters to do that.
EG:
class ReportTestHighChartsAdapter
intention: convert a list of ReportTestResult to series and configure different options of report (eg, title, xAxis etc)
public OptionsHC buildColumnReportV1(){
OptionsHC optionChart = new OptionsHC();
optionChart.chart = new ChartHC("column");
this.setTitle(optionChart);
optionChart.yAxis = new AxisHC(new TitleHC("Fruit eaten"));
.....
return optionChart;
}
OptionsHC is a class that represent option obj in the HighCharts framework.
The final step is converting OptionHC to Json and use it in JavaScript (common use of highCharts)
What's ReportBase?
ReportBase class has the strategy to implements the final called to DB, also manage the transaction
public class ReportTestReport extends ReportBase<ReportTestResult, ReportTestParam> {
...
protected List<TResult> execute(Class<TResult> classT) {
List<TResult> resultDTO = null;
CallableStatement callableStatement = null;
Logger.debug("Running procedure> " + this.getProcedureName());
Transaction tx = Ebean.beginTransaction();
String sql = ProcedureBuilder.build(this.getProcedureName(), this.countParameters());
Logger.debug("SQL > " + sql);
try {
Connection dbConnection = tx.getConnection();
callableStatement = dbConnection.prepareCall(sql);
this.getFilter().setParametersInCallableStatement(callableStatement);
ResultSet rs = callableStatement.executeQuery();
resultDTO = ResultSetUtils.populateInList(classT, rs);
Ebean.commitTransaction();
Logger.debug("commitTransaction > " + sql);
} catch (Exception e) {
Ebean.rollbackTransaction();
Logger.debug("rollbackTransaction > " + sql);
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
Ebean.endTransaction();
}
return resultDTO;
}
...
}
Currently the support for stored procedures in Ebean is not orientated to what you are trying to do. Hence you are not going to get much joy from using CallableSql or RawSql.
>> a class to map the row (resultSet) I think that's the best way to work around performance and clarity
Yes, I can understand your motivation.
>> How to convert ResultSet into model
Currently there is no good solution. The best solution would be to enhance RawSql so that you can set a ResultSet onto it. One of the things RawSql does is provide the mapping of resultSet columns to model properties and that is what Ebean needs internally. The enhancement/code change would be to be able to set a resultSet onto the RawSql object ... and get Ebean internally to skip the creation of the resultSet ( preparedStatement, binding parameters and executeQuery()). In terms of Ebean internals this is all done in the CQuery.prepareBindExecuteQueryWithOption() method. That is, if the RawSql has already provided a resultSet skip those things.
The big benefit of doing this rather than just rolling your own row -> model mapping code is that the resulting beans would all still have lazy loading / partial object knowledge etc. They would behave exactly like any other beans that Ebean builds as part of it query mechanism.
So that said, I'm personally away for a week ... so you aren't going to hear back from me until after that. If you want to get into it yourself then internally CQuery.prepareBindExecuteQueryWithOption() is the code you will need to modify.
If you have been following the ebean google group you'll know that but just in case you have not been note that the Model and Finder objects from Play have been incorporated into Ebean just in the last week. This helps both projects ... reduces confusion etc. The Ebean source in github master is at 4.0.4 and the bytecode enhancement in 4.x is different and I don't believe supported in Play.
I'm basically going offline for a week now so I'll look back into this after that.
Cheers, Rob.

Update table on mysql after a bigdecimal is declared

I have the following work on my application, in which I am trying to update the value total on my mysql database table called "porcobrar2012". However, the only value that gets updated is the last one generated in the while loop. Why? all values are been printout on the screen with no problem, but those values are not getting updated in the database.
Here is the code:
BigDecimal total = new BigDecimal("0");
try
{
//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//Connection connection=DriverManager.getConnection("jdbc:odbc:db1","","");
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost/etoolsco_VecinetSM?user=etoolsco&password=g7Xm2heD41");
Statement statement=connection.createStatement();
String query;
query="SELECT * FROM porcobrar2012";
ResultSet resultSet=statement.executeQuery(query);
while(resultSet.next())
{
out.println(resultSet.getString(2)+"");out.println(resultSet.getBigDecimal(3)+"");out.println(resultSet.getBigDecimal(4)+"");out.println(resultSet.getBigDecimal(5)+"");out.println(resultSet.getBigDecimal(6)+"");out.println(resultSet.getBigDecimal(7)+"");out.println(resultSet.getBigDecimal(8)+"");out.println(resultSet.getBigDecimal(9)+"");out.println(resultSet.getBigDecimal(10)+"");out.println(resultSet.getBigDecimal(11)+"");out.println(resultSet.getBigDecimal(12)+"");out.println(resultSet.getBigDecimal(13)+"")out.println(resultSet.getBigDecimal(14)+"");out.println(resultSet.getBigDecimal(15)+"");
total = resultSet.getBigDecimal(3).add(resultSet.getBigDecimal(4)).add(resultSet.getBigDecimal(5)).add(resultSet.getBigDecimal(6)).add(resultSet.getBigDecimal(7)).add(resultSet.getBigDecimal(8)).add(resultSet.getBigDecimal(9)).add(resultSet.getBigDecimal(10)).add(resultSet.getBigDecimal(11)).add(resultSet.getBigDecimal(12)).add(resultSet.getBigDecimal(13)).add(resultSet.getBigDecimal(14)).add(resultSet.getBigDecimal(15));
String query1;
query1="UPDATE porcobrar2012 SET total=total";
PreparedStatement ps = connection.prepareStatement(query1);
ps.executeUpdate();
out.println(total);
}
connection.close();
statement.close();
}
catch (Exception e)
{
//e.printStackTrace();
out.println(e.toString());
}
It's because the update closes the existing result set. But I would ask why you aren't doing the addition in a single UPDATE statement without any prior query, at the database, no loops, no BigDecimals. Rule one of database programming is 'don't move the data further than you need to'. It would be many times as efficient to just write "UPDATE porcobrar2012 SET a=b+c+d+...". And you can remove the Class.forName() call too: it hasn't been required for years.

How to validate username from MySql with JSP

hello guys i am try to validate username from the database with the username that the user entered in the html from, assume
un//be the variable where username entered now from html form is stored
now how to retrieve all the columns of the uname from user table
uname //column name in mysql for usernames
user //table name in mysql
and check weather the username i.e,un entered now is present or not in the database
i am using
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/mebps","root","admin");
Statement stmt = (Statement) con.createStatement();
ResultSet rs = stmt.executeQuery("select un from userinfo");
while(rs.next())
{
if(rs.getString("uname") == un)
{
out.println("user is present");
}
}
There are at least two major mistakes:
You're comparing string instances by == instead of comparing their values by equals() method. The proper line would be if (rs.getString("uname").equals(un)).
You're not letting the DB do the job of returning the right row, instead you're copying the entire DB table into Java's memory and doing the comparison in Java. This is very inefficient. Make use of SQL powers the smart way so that it always returns exactly the information you need. There's for example a WHERE clause.
On an unrelated note, you seem not to be closing DB resources properly after use. This will result in resource leaking which is also a bad idea as it may cause your application to crash on long term. Further, the column name uname and un are not the same. But I'll assume it to be careless oversimplifying of the example.
Here's a minor rewrite:
public boolean exist(String username) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
boolean exist = false;
try {
connection = database.getConnection();
statement = connection.prepareStatement("SELECT uname FROM userinfo WHERE uname=?");
statement.setString(1, username);
resultSet = statement.executeQuery();
exist = resultSet.next();
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
return exist;
}
You see, if there's a match, then it returns true (at least one record), otherwise false (no one record). No need to copy the entire table into Java's memory and crawl through it in Java.
Last but not least, this code doesn't belong in a JSP file, but in a normal Java class, starting with a servlet. See also our servlets wiki page to learn more about it.

REST Web Service to consume MySQL DB

I'm building a REST WebService with JAX-RS and Tomcat to consume a MySQL Database.
I'm following this model:
#Path("/login")
public class Login {
String username;
String password;
// This method is called if POST is requested
#POST
#Produces(MediaType.APPLICATION_XML)
public String loginResponseXML(#FormParam("username") String user, #FormParam("password") String pass) {
//Connection to MySQL Database
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/sakila", "root","larcom");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("Select first_name, last_name From actor where first_name='" +
user + "' and last_name='" + pass + "'");
while (rs.next()){
System.out.println(rs.getString("first_name") + " " + rs.getString("last_name"));
username = rs.getString("first_name");
password = rs.getString("last_name");
}
}
catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
if (user.equals(username) && pass.equals(password)) {
return ("<?xml version=\"1.0\"?>" + "<auth>200" + "</auth>"); //Success
//return "Success!";
} else {
return ("<?xml version=\"1.0\"?>" + "<auth>404" + "</auth>"); //Damn
//return "Damn!";
}
}
}
I call this method with:
HttpPost httppost = new HttpPost("http://192.168.15.245:8080/org.jersey.andre/rest/login");
Now, my question is:
If I want to query the DB for another table I have to create a new class like Login and make the JDBC connection again?
A new class and a new JDBC connection for each class that make a query to the DB? Performance issues?
Hope you can understand.
Thanks in advance.
A few tips are in order here: Please isolate the DB based code to a "data layer" so to speak...only perform dispatching/business logic within your resource classes.
Now If you are querying a different table, you WILL have a different query! You could either use the same connection (bad) or create a new one and fire a different query(s).
Now whether each resource hits a different table or the same table with a different query depends on your choice of 'representation' for that resource. There is a reason a RDB schema has multiple tables and it's quite common you'll have a different query involving multiple tables or to mutually independent tables.
Performance issues: For 'fresh data' you ARE always going to hit the DB so to speak. If you want to optimize that either develop your own cache (extremely hard) or use approaches like memcached or ehcache to boost performance - before you decide to do that make sure you verify if it's worth it.
Are you going to be having about 1000 DB hits per second? You probably need some performance boosting/handling. Per day...maybe not. Per 2-3 days...YAGNI (You ain't gonna need it, so don't worry for now)
So, for every 'resource' that you design in your application (Login is NOT a resource: See related post: Why is form based authentication NOT considered RESTful?) choose the representation. It may involve different queries etc., for you to return json/xml/xhtml (whatever you choose). Each 'DB related call' should be isolated into it's own 'data layer' - I suggest go with Spring JDBC to make your life easier. It'll take the burden of JDBC plumbing off your shoulders so you can focus on creating your DAOs (Data Access Objects - a patter for Data Access classes. All DAOs logically belong in the data layer)
Hope this helps