Java code for getting data from SQL server to MongoDB - java

I have been struggling with my Mongo-SQL code for a while and still need your help :)
I have a problem while transferring data from an SQL server database to MongoDB. My problem is that I can't do calculations like AVERAGE() or SUM() on my data since I saved them as string in MongoDB. I thought that the numbers would be integers since I got them from my SQL server database where they are stored as integers using the code below. I see now that I use getString() when getting the values. Is that why the numbers are strings in MongoDB? How can I get them as integers? I really want to be able to manipulate them as numbers! Also, some values in SQL server are datetime, so I will need a lot of 'if' statements and different 'get' methods to get all the types right in MongoDB. Does anyone have a good solution to this problem?
StringBuilder orderstatus = new StringBuilder();
orderstatus.append("SELECT * FROM dbo.fact_orderstatus");
PreparedStatement t = connect.prepareStatement(orderstatus.toString());
DBCollection orderstat = db.getCollection("Orderstatus");
ResultSet v = t.executeQuery();
ResultSetMetaData rsm = t.getMetaData();
int column = rsm.getColumnCount();
while (v.next()) {
BasicDBObject orderObj = new BasicDBObject();
for(int x=1; x<column +1; x++){
String namn= rsm.getColumnName(x);
String custNum = (v.getString(x));
if (custNum != null && !custNum.trim().isEmpty()
&& custNum.length() != 0)
orderObj.append(namn, custNum);
}
orderstat.insert(orderObj)

You can utilize the getColumnType() method on your result set.
Since you're using SQL-server I would suggest reading this first:
http://msdn.microsoft.com/en-us/library/ms378668.aspx
This SO question/answer is likely to be helpful too:
Most efficient conversion of ResultSet to JSON?

Related

How to retrieve all the tables from database using Java

I am using JDBC and PostgreSQL as database, I was trying to create a logic in such a way that we can fetch all the data from a table, whatever table name user gives in the input it should get fetched, but the issue here is, I don't know how to do that.
Whenever we used to fetch table data from the database we are required to specify the the type of data we are getting on every index while we use ResultSet.
How to overcome from this hardcoded need of providing this metadata and make our code more general for any table with any number of columns and with any type
My code:
Statement sttm = con1.createStatement();
System.out.println("Enter table name (usertable)");
String name = sc.next();
String tableData="";
String qu = "select * from "+name;
ResultSet rs =sttm.executeQuery(qu);
while(rs.next()) {
// here we need to define the type by writing .getInt or getString
tableData = rs.getInt(1)+":"+rs.getString(2)+":"+rs.getInt(3);
System.out.println(tableData);
}
System.out.println("*********---------***********-----------**********");
sttm.close();
Anyone please suggest me some way to do it.
You can use ResultSet.getObject(int). getObject will automatically retrieve the data in the most appropriate Java type for the SQL datatype of the column.
To retrieve the number of columns, you can use ResultSet.getMetaData(), and then use ResultSetMetaData.getColumnCount() to retrieve the number of columns.
In short, to print all columns of all rows, you can do something like:
try (ResultSet rs = stmt.executeQuery(qu)) {
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
StringBuilder tableData = new StringBuilder();
for (int colIdx = 1; colIdx <= columnCount; colIdx++) {
tableData.append(rs.getObject(colIdx));
if (colIdx != columnCount) {
tableData.append(':');
}
}
System.out.println(TableData);
}
}
You can also use ResultSetMetaData to get more information on the columns of the result set, for example if you need specific handling for certain types of columns. You can use getColumnType to get the java.sql.Types value of the column, or getColumnTypeName to get the type name in the database, or getColumnClassName to get the name of the class returned by ResultSet.getObject(int/String), etc.
However, as Sorin pointed out in the comments, accepting user input and concatenating it into a query string like you're currently doing, makes you vulnerable to SQL injection. Unfortunately, it is not possible to parameterize object names, but you can mitigate this risk somewhat by 1) checking the table against the database metadata (e.g. DatabaseMetaData.getTables), and 2) using Statement.enquoteIdentifier (though this won't necessarily protect you against all forms of injection).
If you want to print data of any table from a database then check my github project over CRUD java MySQL
https://github.com/gptshubham595/jdbc_mysql_CRUD-JAVA-
These are implemented

Get a BigInt value from a resultset (oracle db) in java

I want to get a BigInt value from oracle database in jdbc. getBigInt() or getBigInteger() does not work like getInt(). Here is the code snippet:
public List<Employee> getAllEmployees()
{
List<Employee> employeeList = new ArrayList<Employee>();
try
{
//typical jdbc coding
Connection conn = DBUtil.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM employee1");
while(rs.next())
{
Employee employee = new Employee(rs.getString("emp_id"), rs.getString("name"), rs.getBigInt("emp_mob"));
employeeList.add(employee);
}
DBUtil.closeConnection(conn); //close connection
}
catch(Exception e)
{
e.printStackTrace();
}
return employeeList;
}
emp_mob column in the table contains big integer values.
The BIGINT data type is an 8-byte binary number, which means that the matching Java type is a long, so use getLong():
long mob = rs.getLong("emp_mob");
If the column is NULL-able, use Java type Long, and call wasNull() after calling getLong():
Long mob = rs.getLong("emp_mob");
if (rs.wasNull())
mob = null;
Alternatively, if you want a Java BigInteger, call getBigDecimal() and convert it:
BigDecimal decimal = rs.getBigDecimal("emp_mob");
BigInteger mob = (decimal == null ? null : decimal.toBigInteger());
The proper way is .getObject(colIdx, BigInteger.class);, but whether that'll actually work depends on your JDBC driver. It probably won't, but you should try it: If it does, there you go. Simple, efficient, no issues there.
If it doesn't, you should probably use .getBigDecimal(). This is another way that a JDBC driver might not actually support, so try it out.
If that's a failure too, your last real resort is .getString, and then pass that to BigInteger to reparse into a number. This is rather inefficient. What is the type of the column/expression in your SQL? It'd help to know, and that's a good place to search the docs.
Use BigInteger.valueOf(rs.getLong("emp_mob"))
And this way is safer.

getting ResultSet's values dynamically

Is there any way to get ResultSet's values dynamically? here is the code below to make my question clear.
while(rsltSet.next())
{
arr[i][0] = rsltSet.getInt(1)+"";
arr[i][1] = rsltSet.getInt(2)+"";
arr[i][2] = rsltSet.getString(3)+"";
arr[i][3] = rsltSet.getString(4)+"";
arr[i][4] = rsltSet.getString(5)+"";
}
I tried to use code below in a for loop, it gave me an exception which I cannot get the detail of.
for(int j=1;j<columnCount;j++)
arr[i][j] = rslt2.getObject(j)+"";
How can I get the values of ResultSet without specifyinh whether it is integer or string or date?
If you want the type info use the ResultSetMetaData from the ResultSet.getMetaData() call. Otherwise, you can always use getObject(j).toString().

ResultSet NullPointerException

I have a stored procedure, I want to call it from JDBC, I got null pointer exception in the line"
while (restuls.next()) {
My code is:
Connection con = Database.getConnection();
CallableStatement callableStatement = null;
try {
String storedProcedure = "{call getAllCustomerAddresses(?,?,?,?,?,?,?)}";
callableStatement = con.prepareCall(storedProcedure);
callableStatement.setInt(1, this.getID());
callableStatement.registerOutParameter(2,
java.sql.Types.INTEGER);
callableStatement.registerOutParameter(3,
java.sql.Types.VARCHAR);
callableStatement.registerOutParameter(4,
java.sql.Types.INTEGER);
callableStatement.registerOutParameter(5,
java.sql.Types.INTEGER);
callableStatement.registerOutParameter(6,
java.sql.Types.INTEGER);
callableStatement.registerOutParameter(7,
java.sql.Types.VARCHAR);
callableStatement.execute();
System.out.println(callableStatement.getInt(2));
System.out.println(callableStatement.getString(3));
System.out.println(callableStatement.getInt(4));
System.out.println(callableStatement.getInt(5));
System.out.println(callableStatement.getInt(6));
System.out.println(callableStatement.getString(7));
ResultSet restuls = callableStatement.getResultSet();
while (restuls.next()) {
int addressID = restuls.getInt(2);
String label = restuls.getString(3);
int regionID = restuls.getInt(4);
int areaID = restuls.getInt(5);
int cityID = restuls.getInt(6);
String description = restuls.getString(7);
this.addresses.add(new CustomerAddressImpl(this, label,
description, RegionImpl.getInstance(regionID),
AreaImpl.getInstance(areaID), CityImpl
.getInstance(cityID), addressID));
}
look at the code, the System.out.println is working , and It is printing the right values from database, so why the results set is null please??
another thing, I must use result set because the stored procedure returns many rows.
I am really confusing why I can print the right values but the result set is null
Thanks in advance
Edit
If you want to give you the stored procedure tell me please
Stored Procedure
ALTER PROCEDURE [dbo].getAllCustomerAddresses(
#customerID INT,
#addressID INT OUTPUT,
#label VARCHAR(200) OUTPUT,
#regionID INT OUTPUT,
#areaID INT OUTPUT,
#cityID INT OUTPUT,
#description TEXT OUTPUT
)
AS
SET NOCOUNT Off;
SELECT #addressID = [ID],
#label = [label],
#regionID = [regionID],
#areaID = [areaID],
#cityID = [cityID],
#description = [description]
FROM Customer_Address
WHERE customerID = #customerID
execute() method of PreparedStatement returns true if result set presents and false otherwise. You do not check the return value of execute(). I think that if you do that you see that it is false.
The reason should be in your stored procedure that IMHO does not return value. So, try to analyze it to understand the problem.
Here are recommendations I can give you:
Use executeQuery() that directly returns ResaultSet instead of execute(). I think this is more convenient.
Avoid using stored procedures that couple your platform independent java code with specific type of database. Try to write all logic in java and use portable SQL statements only.
The last time I saw pure JDBC code was about 10 years ago. There are a lot of tools that help you to avoid writing SQL inside java code. Take a look on JPA, Hibernate, iBatis etc.
Your stored procedure doesn't actually produce a ResultSet because you are using output parameters (not 100% sure, I don't have a SQL Server handy to test).
You may just need to call CallableStatement.getObject(int) or CallableStatement.getObject(String) (or a type specific getter) to get the values instead. If you want to process as a ResultSet, then you should not use the output parameters in your stored procedures, but write the stored procedure as a select without assigning to output parameter. That will create a result set from the stored procedure
Another possibility might by that your stored procedure is first returning one or more update counts before returning the result set. The boolean return value of execute() indicates whether the first result is an update count or a ResultSet. You will need to repeatedly call getMoreResults() and getUpdateCount() to be sure you have processed every result.
Your posted stored procedure contains SET NOCOUNT OFF which signals to SQL Server (or Sybase) that you want update (and I believe select) counts returned as well, you might want to try using SET NOCOUNT ON.
You can also try to process the results of execute() like this to find out if there are indeed multiple update counts etc before the result set:
boolean result = pstmt.execute();
while(true)
if (result) {
ResultSet rs = pstmt.getResultSet();
// Do something with resultset ...
} else {
int updateCount = pstmt.getUpdateCount();
if (updateCount == -1) {
// no more results
break;
}
// Do something with update count ...
}
result = pstmt.getMoreResults();
}
See also Java SQL: Statement.hasResultSet()?

Use of getters in ResultSets

I am trying to write java code to access a table 'customer' with columns 'customer_id', 'email', 'deliverable', and 'create_date'
I have
Connection conn = DriverManager.getConnection(connectionUrl, connectionUser, connectionPassword);
Statement constat = conn.createStatement();
String query = "SELECT * FROM customer WHERE customer_id LIKE " + customerId;
ResultSet rtn = constat.executeQuery(query);
Customer cust = new Customer(rtn.getInt("customer_id"), rtn.getString("email"), rtn.getInt("deliverable"), rtn.getString("create_date"));
conn.close();
return cust;
I am receiving the error:
java.sql.SQLException: Before start of result set
As far as I can tell, my error is in the line where I am creating a new Customer object, but I cannot figure out what I am doing wrong. Can anyone offer me some help? Thanks!
You must always go to the next row by calling resultSet.next() (and checking it returns true), before accessing the data of the row:
Customer cust = null;
if (rtn.next()) {
cust = new Customer(rtn.getInt("customer_id"),
rtn.getString("email"),
rtn.getInt("deliverable"),
rtn.getString("create_date"));
}
Note that you should also
use prepared statements instead of String concatenation to avoid SQL injection attacks, and have more robust code
close the connections, statements and resultsets in a finally block, or use the try-with-resources construct if using Java 7
Read the JDBC tutorial
You should call ResultSet.first() to move the result to the first position. The result set is a programming convention not to retrieve the whole result of the query and keep in memory. As such, its interface is quite low level and you must explicit select the row via methods like first(), last() or next() (each returns true to check if the requested row index is in the set)
You need to add
rtn.next();
before you use the result set.
Usually this is done as
while (rtn.next()) {
<do something with the row>
}

Categories