JDBC MYSQL FK implementation - java

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);
}
}

Related

JDBC: "SQLException:Column name is not found"

I have tried to use these two questions as a reference
JAVA - SQLException throws exist column not found
Strange SQLException: Column not found
However, none of it helped my case. I keep receiving
java.sql.SQLException: Column 'debut' not found.
this is my SQL
private List<MemberModel> getModelFromNickname(String test) throws SQLException {
List<MemberModel> result = new ArrayList<>();
String sql = "select distinct " +
"m.name," +
"m.visual," +
"m.branch, " +
"m.illustrator, " +
"m.debut3D AS debut " +
"FROM " +
"member_list as m, " +
"nickname AS n " +
"WHERE n.nick_id = m.nick AND n.nickname LIKE ?";
ResultSet ret= sqlAdapter.select(
sql, 1,test
);
while (ret.next()){
result.add(fillRecord(ret));
}
return result;
}
this is my MYSQLAdapter
public ResultSet select(String sql,int option, Object... params) throws SQLException {
PreparedStatement query;
try{
logger.info(params.length);
query = getConnection().prepareStatement(sql);
}
catch (Exception e){
throw new Error("Problem "+ e);
}
resolveParameters(query,option, params);
return query.executeQuery();
}
this is my fillRecord command
private static MemberModel fillRecord(ResultSet resultSet) throws SQLException {
MemberModel member = new MemberModel();
member.name =resultSet.getString("name");
member.branch = resultSet.getString("branch");
member.debut_3d = resultSet.getBoolean("debut");
member.visual = resultSet.getString("visual");
member.illustrator = resultSet.getString("illustrator");
return member;
}
while this is my memberModel
public class MemberModel {
public String name = "";
public int social_media = 0;
public int nick = 0;
public String branch = "";
public boolean debut_3d= true;
public String illustrator ="";
public String visual = "";
}
I tried to use
ResultSetMetaData rsmd = sqlAdapter.getConnection().prepareStatement(sql).getMetaData();
for(int i =1; i<= rsmd.getColumnCount();i++){
System.err.println(rsmd.getColumnCount()+"\n"+rsmd.getColumnName(i));
}
which gives me the following (I don't know how it somehow managed to print more than 5. But, all of it except "debut" can be found)
5
name
5
visual
5
branch
5
illustrator
5
debut
5
name
5
visual
5
branch
5
illustrator
5
debut
This indicates that the debut column should exist yet I still get that exception. Where did I do wrong? I make sure that it is case sensitive just in case. The data type for "debut" column is boolean in my localhost XAMPP MySQL. If I erase member.debut_3d = resultSet.getBoolean("debut"); within fillrecord... Everything works perfectly fine
Rather get values by labelName trying column number.
private static MemberModel fillRecord(ResultSet resultSet) throws SQLException {
MemberModel member = new MemberModel();
member.name = resultSet.getString(1);
member.branch = resultSet.getString(3);
member.debut_3d = resultSet.getBoolean(5);
member.visual = resultSet.getString(2);
member.illustrator = resultSet.getString(4);
return member;
}
resultSet.getBoolean("debut3D"); // Instead of "debut"
The column in the database table is called "debut3D".
BTW you are not closing PreparedStatement and ResultSet. I would use try-with-resources.
The column name is "debut3D" not "debut", thats why you are getting the error.
Update below line with correct column name,
member.debut_3d = resultSet.getBoolean("debut3D");

Not getting total records from the database

I have 4 records in my database table, but i am getting only one record from the function. please check my code once. When i call the getMaterialTransferRecords() function inside this function i have another function getMaterialUnit(). I am not able to find the solution. Please any one help me.
This is the query i am executing in my sqlyog. please check it once
Above is my query and below is the result.
This is how i am calling the function.
// Fetch Data from User Table
int startPageIndex = Integer.parseInt(request.getParameter("jtStartIndex"));
int recordsPerPage = Integer.parseInt(request.getParameter("jtPageSize"));
String jtSorting = request.getParameter("jtSorting");
MaterialTransferUtils utils = new MaterialTransferUtils();
//System.out.println("Cash Purchases Start Page Index:"+startPageIndex+" recordsPerPage:"+recordsPerPage);
if(jtSorting != null)
{
jtSorting = jtSorting.replaceAll("material_destn_code", "material_destn_code");
jtSorting = jtSorting.replaceAll("date", "transferred_on");
}
// Fetch Data from Cash Memo Table
mtList = utils.getMaterialTransferRecords(startPageIndex, recordsPerPage,jtSorting);
Please check the code once.
public List<MaterialTransferBean> getMaterialTransferRecords(int startPageIndex, int recordsPerPage,String jtSorting)
{
List<MaterialTransferBean> list = new ArrayList<MaterialTransferBean>();
con=com.s2s.bssb.database.ConnectionFactory.getConnection();
MaterialTransferBean mtbean = null;
String sortStr = "material_destn_code DESC";
if(null != jtSorting)
sortStr = jtSorting;
String query = "SELECT sno,material_loc_code,transferred_on,mr_no,do_no,material_destn_code,material_id,quantity,unit_price, "
+ "gst,remarks FROM material_transfer ORDER BY "+sortStr+" LIMIT "+recordsPerPage+" offset "+startPageIndex+"";
System.out.println(query);
if(con!=null){
try{
ps=con.prepareStatement(query);
rs=ps.executeQuery();
while(rs.next()){
MaterialTransferBean bean = new MaterialTransferBean();
bean.setSno(rs.getInt("sno"));
bean.setMaterial_loc_code(rs.getString("material_loc_code"));
bean.setDate(rs.getDate("transferred_on"));
bean.setMr_no(rs.getString("mr_no"));
bean.setDo_no(rs.getString("do_no"));
bean.setMaterial_destn_code(rs.getString("material_destn_code"));
bean.setQuantity(rs.getDouble("quantity"));
bean.setUnit_price(rs.getDouble("unit_price"));
bean.setAmount(rs.getDouble("quantity")*rs.getDouble("unit_price"));
bean.setGst(((rs.getDouble("quantity")*rs.getDouble("unit_price"))*(rs.getDouble("gst")))/100);
bean.setTtl_amount((rs.getDouble("quantity")*rs.getDouble("unit_price"))+(((rs.getDouble("quantity")*rs.getDouble("unit_price"))*(rs.getDouble("gst")))/100));
bean.setRemarks(rs.getString("remarks"));
mtbean = new MaterialTransferBean();
mtbean = getMaterialUnit(rs.getInt("material_id"));
bean.setMaterial(mtbean.getMaterial());
bean.setUnit(mtbean.getUnit());
list.add(bean);
}
rs.close();
com.s2s.bssb.database.ConnectionDB.close(con);
com.s2s.bssb.database.ConnectionDB.close(ps, con);
}catch(SQLException sql_ex){
sql_ex.printStackTrace();
}
}else{
System.out.println("Connection Not Created");
}
return list;
}
public MaterialTransferBean getMaterialUnit(int material_id){
MaterialTransferBean bean = null;
con=com.s2s.bssb.database.ConnectionFactory.getConnection();
String query = "select material,unit from materials where id=?";
if(con!=null){
try{
ps=con.prepareStatement(query);
ps.setInt(1, material_id);
rs=ps.executeQuery();
while(rs.next()){
bean = new MaterialTransferBean();
bean.setMaterial(rs.getString("material"));
bean.setUnit(rs.getString("unit"));
}
}catch(SQLException sql_ex){
sql_ex.printStackTrace();
}
}
return bean;
}

How can i create a dynamic and reusable method to create a table with java and sqlite

I want to have a method in java to create sqlite tables without knowing the number of columns
public static void createNewTable(String databaseName, String tableName, String typeOfAttribute1, String attribute1) {
// SQLite connection string
String url = "jdbc:sqlite:" + databaseName;
// static SQL statement for creating a new table
String sql = "CREATE TABLE IF NOT EXISTS "+ tableName + " (" + attribute1 + " " + typeOfAttribute1 + ");";
try (Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement()) {
// create a new table
stmt.execute(sql);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
In this specific case i'm forced to create a table with only one column (attribute1). Is possible to have a more reusable approach and create a table without knowing the number of the columns?
I hope that everything is clear
You can use StringBuilder and instead to pass list of columns i suggest to use a List which take an Array[column_name, column_type] like this :
public static void createNewTable(String databaseName, String tableName, List<String[]> columns) {
// SQLite connection string
String url = "jdbc:sqlite:" + databaseName;
String query = "CREATE TABLE IF NOT EXISTS " + tableName + " (";
StringBuilder sql = new StringBuilder(query);
String prefix = "";
for (String[] s : columns) {
sql.append(prefix);
prefix = ", ";
sql.append(s[0]);
sql.append(" ");
sql.append(s[1]);
}
sql.append(");");
System.out.println(sql);
try (Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement()) {
// create a new table
stmt.execute(sql.toString());
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
List<String[]> list = new ArrayList<>();
list.add(new String[]{"col1", "type1"});
list.add(new String[]{"col2", "type2"});
list.add(new String[]{"col3", "type3"});
list.add(new String[]{"col4", "type4"});
list.add(new String[]{"col5", "type5"});
createNewTable("database_name", "table_name", list);
}
This will show you:
CREATE TABLE IF NOT EXISTS table_name (col1 type1, col2 type2, col3 type3, col4 type4, col5 type5);
You can use varargs, which is simply an array. Consider that each odd item is attribute name, each even item is attribute type:
public static void createNewTable(String databaseName, String tableName, String ...attributes) {
if (attributes.length % 2 != 0) throw new IllegalArgumentException(...);
// attributes[0] - 1st attribute name
// attributes[1] - 1st attribute type
for (int i = 0; i < attributes.length-1; i+=2) {
// attributes[i] - i-st attribute name
// attributes[i+1] - 1st attribute type
// ...
}
// ...
}
I hope you can complete rest logic of this method by your self.

How do I get this tuple using AbstractMap?

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().

Is it possible to Convert ArrayList < SelectItem> to ArrayList<Long> in java

I have a list like following:
List<SelectItem> measurementList;
I want to assign measurementList.get(i) into a Long variable.
For example I want to assign it in the following way:
Long sd = measurementList.get(0);
But, it is showing type mismatch. That is really obvious. How can I assign the value from measurementList.get(0) to a Long variable.
Thanks
Code are given below:
public List<SelectItem> measurementList(Long coModAssetId)
{
// log.info("Start");
// log.debug("finding MeasurementSeneorTypeList instance by example using dbMeasurementSeneorTypeList");
List<SelectItem> results;
try {
// Add SELECT with a nested select to get the 1st row
String queryString = "SELECT M.Measurement_Id, M.NAME" +
" FROM ems.COMPANY_MODULE_ASSET CMA, " +
" ems.Asset_Measurement Am," +
" ems.MEASUREMENT M" +
" WHERE CMA.Co_Mod_Asset_Id = ?" +
" And Cma.Asset_Id = Am.Asset_Id " +
" AND AM.MEASUREMENT_ID = M.MEASUREMENT_ID" +
" GROUP BY M.measurement_id, M.NAME" +
" ORDER BY M.name";
MeasurementSeneorTypeListWork work = new MeasurementSeneorTypeListWork();
work.coModAssetId = coModAssetId;
work.queryString = queryString;
getSession().doWork(work);
results = work.results;
} catch (RuntimeException re) {
// log.error("getMostRecentObservationId() failed", re);
throw re;
}
//log.info("End");
return results;
}
Class definition
public class MeasurementSeneorTypeListWork implements Work {
List<SelectItem> results = new ArrayList<SelectItem>();
private String queryString;
private Long coModAssetId;
#Override
public void execute(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(queryString);
int index = 1;
ps.setLong(index++, coModAssetId);
ResultSet rs = ps.executeQuery();
while(rs.next())
{
//String userName = PropertyReader.getLabel(rs.getString(2));
Long id = rs.getLong(1);
SelectItem item = new SelectItem(id, null);
results.add(item);
}
rs.close();
ps.close();
}
}
}
If your SelectItem type is javax.faces.model.SelectItem, then you have a getValue() method that you can use.
Long sd = (Long) measurementList.get(i).getValue();
Note: you're using the 2-argument constructor SelectItem(Object value, String label) to create your items for the list, but since the second parameter is always null, you could use SelectItem(Object value) instead.
You can use the .longValue() method:
(measurementList.get(i)).longValue()
This returns the numeric value represented by this object after conversion to type long.

Categories

Resources