How do I get this tuple using AbstractMap? - java

I am using PostgreSQL in Java and I'm executing the query, which selects coordinates from a Database.
Prior, the Points were saved in an ArrayList. Now I want to print out the Date with the Point. I want to get a Pair of Dates and Points via AbstractMap and print them out together.
But I don't know how to get the Dates and how to print the coordinates and Dates in one line.
Here is the relevant part of first class:
public ArrayList<AbstractMap.SimpleEntry<Point, Date>> getStartingPointCoordinates(String ab, String bis) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
ArrayList<AbstractMap.SimpleEntry<Point, Date>> list = new ArrayList<AbstractMap.SimpleEntry<Point,Date>>();
String query = "select ST_Transform(target_cand_geom, 4326) as geom from fcd_osm_1day WHERE source_candidate_nr = ? and source_time between ? and ? ";
try {
// prepare statement
connection = DatenbankAdapter.getInstance().getConnection();
statement = connection.prepareStatement(query);
statement.setInt(1, 1); // source_candiddate_nr = 1, weil dies immer dem Einstieg der Taxifahrt entspricht
statement.setTimestamp(2, Timestamp.valueOf("2014-10-07 " + ab)); // hole alle daten von
statement.setTimestamp(3, Timestamp.valueOf("2014-10-07 " + bis)); // hole alle daten bis
resultSet = statement.executeQuery();
/*
* Add the geometry types to the connection. Note that you
* must cast the connection to the pgsql-specific connection
* implementation before calling the addDataType() method.
*/
connection = ((DelegatingConnection) connection).getInnermostDelegate();
((org.postgresql.PGConnection) connection).addDataType("geometry", Class.forName("org.postgis.PGgeometry"));
while (resultSet.next()) {
Point geom = (Point) ((PGgeometry) resultSet.getObject(1)).getGeometry();
list.add(geom);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (resultSet != null)
resultSet.close();
if (statement != null)
statement.close();
if (connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
Here is the test class:
public class DatenbankAdapterTest {
#Test
public void testCoordinateQuery() {
DatenbankAdapter datenbankAdapter = DatenbankAdapter.getInstance();
ArrayList<SimpleEntry<Point,Date>> objects = datenbankAdapter.getStartingPointCoordinates("00:00:00", "24:00:00");
for (SimpleEntry<Point, Date> list : objects)
System.out.println(list.getKey() + ", " + list.getValue());
Assert.assertTrue(!objects.isEmpty());
}
}

Add a column source_time to the result set
String query = "SELECT ST_Transform(target_cand_geom, 4326) AS geom, "
+ "source_time "
+ "FROM fcd_osm_1day "
+ "WHERE source_candidate_nr = ? AND source_time BETWEEN ? AND ?";
...
Timestamp t = resultSet.getTimestamp();
Date date = new Date(t.getTime()); // java.util.Date
list.add(new AbstractMap.SimpleEntry(geom, date));
Here a problem is hidden. java.util.Date is a date-time class. java.sql.Date is a child class that zeroes the time part. Hence the above solution.
It does not need telling that a Map.Entry is not nice. Better abuse from javafx the Pair class:
List<Pair<Point, Date>> getStartingPointCoordinates(String ab, String bis) {
List<Pair<Point, Date>> list = new ArrayList<>();
...
return list;
BTW Pair<K,V> has the same getters: K getKey() and V getValue().

Related

get both output parameter and ResultSet values from SQL Server stored procedure

I am trying to get the output parameter for passing into another SP so I created a test too see if I could get the string from it but an exception gets thrown:
java.sql.SQLException: Invalid state, the ResultSet object is closed
Without the cs.getMoreResults(); another exception is thrown:
java.sql.SQLException: Output parameters have not yet been processed. Call getMoreResults().
If I do remove my if (rs.next()) { then it works.
How do I get the output parameter and still use my if rs.next?
protected String doInBackground(String... params) {
if (userid.trim().equals("Developer")|| password.trim().equals("Dev!n_234"))
isSuccess2=true;
z = getString(R.string.login_succes);
if(userid.trim().equals("")|| password.trim().equals(""))
z = getString(R.string.indsæt_rigtigt_bruger);
else {
try {
Connection con = connectionClass.CONN();
if (con == null) {
z = getString(R.string.Forbindelses_fejl) + "L1)";
} else {
String ID;
ID = setingPreferences.getString("companyid", "");
CallableStatement cs = null;
String query = "{ call [system].[usp_validateUserLogin](?,?,?,?,?)} ";
cs = con.prepareCall(query);
cs.setString(1, userid);
cs.setString(2, password);
cs.setString(3, ID);
cs.setBoolean(4, true);
cs.registerOutParameter(5, Types.VARCHAR);
ResultSet rs = cs.executeQuery();
cs.getMoreResults();
System.out.println("Test : " + cs.getString(5));
if (rs.next()) {
z = getString(R.string.login_succes);
isSuccess = true;
} else {
z = getString(R.string.Invalid_Credentials);
isSuccess = false;
}
}
}
catch (Exception ex)
{
isSuccess = false;
z = getString(R.string.Exceptions)+"L2)";
Log.e("MYAPP", "exception", ex);
}
}
return z;
}
}
You need to process the ResultSet value(s) first, and then retrieve the output parameter value. That's because SQL Server sends the output parameter values after sending the result sets (ref: here).
So, this won't work:
ResultSet rs = cs.executeQuery();
System.out.println(cs.getString(5)); // clobbers the ResultSet
rs.next(); // error
but this should be okay:
ResultSet rs = cs.executeQuery();
if (rs.next()) {
// do stuff
}
System.out.println(cs.getString(5)); // retrieve the output parameter value

Java ResultSet Skipping Records

After a morning of research, I'm stumped on what should be an easy piece of code.
All I want is to get all records from our raw_material table in the test database.
Here is what I am doing:
public static void fetchIthos(ArrayList<String> ithosList, UserDto user) {
// TODO Auto-generated method stub
//get our stuff first - raw materials and doc names and paths
try {
Connection conn = user.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM raw_material where object_id > 0");
do {
String result = rs.getString("raw_material_number").toString();
System.out.println("next item: " + result);
//ithosList.add(rs.getString("raw_material_number"));
} while(rs.next());
}
catch (Exception e) {
ithosList.equals(null);
System.out.println("DB error : " + e);
}
}
Here are the results in mySQL:
so I would expect the first 'result' to be MAN-500-121200000, but it is showing as RAW-001485
I cannot see anywhere in the code that I am 'skipping' the first record, but if I let it go, it will skip the next one to MAN-500-056100000
Am I using the wrong user connection? That is the only thing I can see that affects this.
I thought user.getConnection() would do it for just the regular test database.
Your code seems to be incorrect, the expected loop is rather:
while(rs.next()) {
String result = rs.getString("raw_material_number");
System.out.println("next item: " + result);
}
Consider using try-with-resources statement to close properly your Connection, Statement and ResultSet as next:
try (Connection conn = user.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM raw_material where object_id > 0")) {
// My code here
}
Try like this.
while(rs.next()){
String result = rs.getString("raw_material_number");
System.out.println("next item: " + result);
}
public static void fetchIthos(ArrayList<String> ithosList, UserDto user) {
// TODO Auto-generated method stub
int i = 1;
//get our stuff first - raw materials and doc names and paths
try {
Connection conn = user.getConnection();
Statement st = conn.createStatement();
ResultSet rsCount = st.executeQuery("SELECT COUNT(*) from raw_material");
rsCount.first();
long r = (Long) rsCount.getObject(i);
for (i=1; i < r+1; i++) {
ResultSet rs = st.executeQuery("SELECT * FROM raw_material where object_id =" + i + "");
//moves to the first record
rs.first();
do {
String result = rs.getString("raw_material_number");
System.out.println("next item: " + result);
ithosList.add(rs.getString("raw_material_number"));
} while(rs.next());
}
}
catch (Exception e) {
ithosList.equals(null);
System.out.println("DB error : " + e);
}
}
Hacky way of doing it but it got it to work for now, at least until the senior developer returns from bereavement. Keep in mind I've had only 3 months of java, baptism by fire. lol.

JDBC MYSQL FK implementation

I am trying to implement FK relation from MySQL into JAVA using JDBC. I have a list of Garaz objects and each Garaz has a list of Auto (cars) objects. I have very mixed data.
My MySQl DB is ok and I try to do it like this:
public static ArrayList <Garaz> selectRecords() throws SQLException {
Connection dbConnection = null;
Statement statement = null;
String selectTableSQL = "SELECT Garaz.G_ID, Garaz.Nazwa, Garaz.Adres, Garaz.LiczbaMiejsc, Garaz.LiczbaPoziomow, " +
"Garaz.Czynny, Auta.A_Id, Auta.Model, Auta.Kolor, Auta.IloscDrzwi, Auta.Rejestracja\n" +
"FROM Garaz\n" +
"LEFT JOIN Auta\n" +
"ON Garaz.G_Id=Auta.G_Id\n" +
"ORDER BY Garaz.G_Id; ";
// ArrayList lista = new ArrayList <Garaz>();
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
System.out.println(selectTableSQL);
// execute select SQL stetement
ResultSet rs = statement.executeQuery(selectTableSQL);
while (rs.next()) {
int g_id = rs.getInt("G_ID");
String nazwa = rs.getString("NAZWA");
String adres = rs.getString("ADRES");
int lmiejsc = rs.getInt("LICZBAMIEJSC");
int lpoz = rs.getInt("LICZBAPOZIOMOW");
boolean czynny = rs.getBoolean("CZYNNY");
ArrayList lista2 = new ArrayList <Auto>();
int a_id = rs.getInt("A_Id");
String model = rs.getString("Model");
String kolor = rs.getString("Kolor");
int ildrzwi = rs.getInt("IloscDrzwi");
String rejestracja = rs.getString("Rejestracja");
Auto d = new Auto(a_id, model, kolor, ildrzwi, rejestracja);
if (a_id !=0){
lista2.add(d);
}
Garaz f = new Garaz(g_id, nazwa, lista2, adres, lmiejsc, lpoz, czynny);
lista.add(f);
//System.out.println("nazwa : " + nazwa);
//System.out.println("adres : " + adres);
// return lista;
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (statement != null) {
statement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
return lista;
}
I don't understand how to read from ResultSet rs in the way that: ArrayList Garaz contains objects (Garaz) and each Garaz object contains ArrayList Auto. So I have big problem with creating 2 lists (one is part of another) by reading data from rs (ResultSet). I have all Garaz and all Auto from DB tables, but the relation is mixed. Like Garaz1 contains random Auto (cars).
How do I create 2 lists (one is part of another) to keep the relation Auto is part of Garaz based on G_ID?
your result set will provide one result (aka line) for each Garaz and Auto, since thats what the select statement does. So you can...
either parse the resultset as it is, and manually create each Garaz & Auto record you want, but you will have to deal with the duplicate Garaz data.
OR
You can either use a framework like MyBatis to get the get the objects back, or.
OR
Perform a SELECT statement for the list of Garaz, then perform another SELECT statement to get the list of AUTO's back for each Garaz.
Sudo code.....
#Repository
public class StoreDbDAO
{
#Autowired
public void init(#Qualifier("dataSourceCDB") DataSource dataSource) {
this.dataSource = dataSource;
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
private static final String GET_USABLE_RECORDS = "SELECT d.ID, d.HARDWARE_ID " +
" FROM DEVICE d " +
" LEFT JOIN TABLEB o on o.X_ID = d.X_ID " +
" WHERE " +
" d.DEVC_HARDWARE_ID IS NOT NULL " +
" AND o.CODE = ? "";
public List<Map<String, Object>> getStores(String cCode)
{
return simpleJdbcTemplate.queryForList(GET_USABLE_RECORDS, code);
}
}
#Autowired
StoreDbDAO storeDbDAO;
public void caller() {
List> stores = storeDbDAO.getStores();
List<Stores> storeRecords = new ArrayList[stores.size()];
for (Map<String, Object> store: stores)
{
final String storeId = (String) store.get("HARDWARE_ID");
StoreRecord x = new StoreRecord(storeId)
storeRecords.add(x);
List<Map<String, Object>> devicesInTheStore = storeDbDAO.getDevicesForStore(storeId);
// convert these into something useful.
x.setDevicesInStore(convertToList(devicesInTheStore));
}
}
You need to iterate over the result, check if you already created the Garaz object for the G_ID of the row and either use that or create a new one. This can be simplified by sorting on the G_ID field and just create a new Garaz object when the G_ID changes.
As you comment that you don't know how to do this, here is a full example:
public List<Garaz> getAllGaraz() throws SQLException {
List<Garaz> garazList = new ArrayList<Garaz>();
try (
Connection con = getDBConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT Garaz.G_ID, /* other garaz columns */ " +
"Auta.A_Id /*other auta columns */\n" +
"FROM Garaz\n" +
"LEFT JOIN Auta\n" +
"ON Garaz.G_Id=Auta.G_Id\n" +
"ORDER BY Garaz.G_Id");
) {
Garaz currentGaraz = null;
while (rs.next()) {
int garazId = rs.getInt("G_ID");
// Create Garaz only if it is different
if (currentGaraz == null || currentGaraz.getId() != garazId) {
// retrieve other columns
currentGaraz = new Garaz(g_id /* + other garaz columns */);
garazList.add(currentGaraz);
}
int a_id = rs.getInt("A_Id");
// replacement of your condition of a_id != 0
// 0 could be a valid value, check for null instead
if (!rs.wasNull()) {
// retrieve other columns
Auto auta = new Auta(a_id /* + other auta columns */);
// The list of Auta is part of the garaz
currentGaraz.addAuta(auta);
}
}
return garazList;
}
}
public class Garaz {
private final List<Auta> autaList = new ArrayList<Auta>();
private final int id;
public Garaz(int g_id /* + other fields*/) {
id = g_id;
}
public int getId() {
return id;
}
public void addAuta(Auta auta) {
autaList.add(auta);
}
public List<Auta> getAutaList() {
return new ArrayList<Auta>(autaList);
}
}

get data from flat file and insert data into database in Java

I open new question about the extract data and insert to database. I change and modified the code become like this but still not working.
Flat file:
DT|00000001|TMDWH|UNIFI|00380520160|MAH SIEW YIN|11 |JALAN PP 2/8|TAMAN PUTRA PRIMA|PUCHONG|SELANGOR|47100|MALAYSIA|801110-14-5498||||||VOBB||A||11|JALAN PP 2/8|||TAMAN PUTRA PRIMA
DT|00000002|TMDWH|UNIFI|00322012091|JUNITA BINTI JAMAL|6 10 KONDOMINIUM FAJARIA|JALAN PANTAI BARU|KUALA LUMPUR|KUALA LUMPUR|WILAYAH PERSEKUTUAN|59200|MALAYSIA|800129-09-5078||||||VOBB||A|||JALAN PANTAI BARU|6|KONDOMINIUM FAJARIA|KUALA LUMPUR
Program:
public void massageData(String tmp) {
String[] fields = tmp.replace("\"", " ")
.replace("\'","\'\'")
.trim()
.split("\\s*\\|\\s*");
Connection conn = null;
ResultSet rs = null;
PreparedStatement stmt = null;
String actualMSISDN = parseMSISDN(fields[5]);
if (actualMSISDN.length() > 8) {
String [] aNo = getAreaCode(actualMSISDN).split("\\|");
field[0] = getiCtr(parseMSISDN(fields[5]));
String stateCode = lookupStateCode(State);
String sQuery = "insert into DATA_999 ( ,RecordType,RecordNumber,SourceSystemApplicationId,TargetApplicationId,TelNo,Name,HouseNo,StreetName,AppartmentSuite,TownCity,State,PostalCode,Country,NewIC,OldIC,PassportNo,BRN,LatitudeDecimal,LongitudeDecimal,ServiceType,IndicatorType,CreateDate,Filler,Cr_Nl,HouseNo_New,LotNo_New,StreetName_New,AptNo_New,BuildingName_New,LowIDRange,HighIDRange,SectionName) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try {
conn = ds.getConnection();
stmt = conn.prepareStatement(sQuery);
int col = 0;
for (String field : fields) {
stmt.setString(++col, field); // Note: SQL API is 1-based (not zero-based)
}
int dbStat = stmt.executeUpdate();
conn.close();
} catch (SQLException s){
logger.error(s.getMessage());
}
finally {
try {if (stmt != null) stmt.close();} catch (SQLException e) {}
try {if (conn != null) conn.close();} catch (SQLException e) {}
}
}
}
You're actually trying to insert double the amount of fields in 1 row. Also you seem to have an error in your sql query: the first field is absent and there's only a comma there.
It also seems to me that you're not doing anything yourself: you use the advice people give you, change your code and if it doesn't work you create a new question.

How do I abstract my business logic and object defintions away from my database access code?

So I have a database with 2 tables - Workflows and WorkflowSteps I want to use the rows stored there to create objects in java BUT the catch is that I want to have my database code separated from my application code. From one point onwards - when Workflow/WorkflowSteps objects are create the rest of the application will not have to worry about DB access. So here is what I have:
public Workflow getPendingWorkflowId() {
int workflowid = -1;
Statement statement = null;
ResultSet rs = null;
try {
statement = con.createStatement();
rs = statement.executeQuery("SELECT id FROM xxx.workflows WHERE status = 'NOT-YET-STARTED' LIMIT 1");
while (rs.next()) {
workflowid = rs.getInt("id");
}
statement.close();
rs.close();
} catch (SQLException ex) {
Logger.getLogger(DBAccessor.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error fetching workflows id");
}
return new Workflow(workflowid);
}
Each workflow object has a List to store the steps that pertain to a particular Workflow and then each WorkflowStep has a Map which is used to store data taken from a 3rd table:
public List<WorkflowStep> getUnworkedStepsByWFId(int id) {
//can be changed
ArrayList<WorkflowStep> steps = new ArrayList<WorkflowStep>();
Statement statement = null;
ResultSet rs = null;
try {
statement = con.createStatement();
rs = statement.executeQuery("SELECT * FROM `workflow_steps` WHERE `workflow_id` =" + id + " AND status = 'NOT-YET-STARTED'");
while (rs.next()) {
steps.add(new WorkflowStep(rs.getInt(1), rs.getInt(3), rs.getInt(4)));
}
statement.close();
rs.close();
} catch (SQLException ex) {
Logger.getLogger(DBAccessor.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error fetching workflows id");
}
return steps;
}
And here is the query for the 3rd table:
public Map getParametersForStep(int workflowId, int workstepPos) {
Statement statement = null;
ResultSet rs = null;
Map<String, String> hMap = new HashMap<String, String>();
try {
statement = con.createStatement();
//MIGHT BE WRONG
rs = statement.executeQuery("SELECT wf.id AS workflowID, ws_steps.id AS workflowStepsID, name, param_value, pathname FROM workflows AS wf INNER JOIN workflow_steps AS ws_steps ON wf.id = ws_steps.workflow_id INNER JOIN ws_parameters ON ws_parameters.ws_id = ws_steps.id INNER JOIN submodule_params ON submodule_params.id = ws_parameters.sp_id AND wf.id =" + workflowId + " AND ws_steps.workflow_position =" + workstepPos);
String paramName = null;
String paramValue = null;
while (rs.next()) {
paramName = rs.getString("name");
if (rs.getString("param_value") == null) {
paramValue = rs.getString("pathname");
} else {
paramValue = rs.getString("param_value");
}
hMap.put(paramName, paramValue);
}
statement.close();
rs.close();
return hMap;
} catch (SQLException ex) {
Logger.getLogger(DBAccessor.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error fetching workflow step parameters names");
}
return Collections.emptyMap();
}
Having this code in mind I end up with the following "procedure" to initialize a Workflow with all its WorkflowSteps and their Parameters:
Workflow wf = db.getPendingWorkflowId();
wf.initSteps(db.getUnworkedStepsByWFId(wf.getId()));
Iterator<WorkflowStep> it = wf.getSteps();
while(it.hasNext()) {
WorkflowStep step = it.next();
step.setParameters(db.getParametersForStep(wf.getId(), step.getPosInWorkflow()));
}
I think I have a good level of decoupling but I wonder if this can be refactored somehow - for example probably move the step.setParameters to a method of the WorkflowStep class but then I would have to pass a reference to the database connection (db) to a WorkflowStep object but in my view this will break the decoupling? So how would you people refactor this code?
It seems that you are rolling your own ORM. My suggestion would be to use one of existing ones like Hibernate.
This is the function of an Object Relational Mapper. It serves to abstract your DB access away from your business model. In fact, used properly, an ORM library allows you to write no database code at all.

Categories

Resources