Yesterday I posted a question regarding retrieving data from a Db and iterating over it. Someone helpfully pointed my to JDBI and away from raw data types.
Caveats: I am a tester forst and foremost and have just started to explore JDBI for some automated tests.
So, I think I've improved the previous solution but I am just struggling with implementing the best way to iterate over my dataset now it is retrieved.
Here is my method to return the dataset:
public List<FlightDataBean> lastFlightBookedResults(String supplierCode, String channel) {
String sqlQuery = getData(supplierCode, channel);
List<FlightDataBean> dataSet = jdbi.withHandle(handle ->
handle.createQuery(sqlQuery)
.mapToBean(FlightDataBean.class)
.list());
return dataSet;
}
Here is my Bean class:
public class FlightDataBean {
private String startDate;
private String origin;
private String destination;
public FlightDataBean(){
}
public FlightDataBean(String startDate, String origin, String destination) {
this.startDate = startDate;
this.origin = origin;
this.destination = destination;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
}
Here is an example of the returned dataset, 30 rows of 3 columns:
Clearly I can retrieve individual results by doing suchlike:
List<FlightDataBean> resultSet;
resultSet = getFlightData(syndicatorName);
String startDate = (resultSet.get(0).getStartDate());
String origin = String.valueOf((resultSet.get(1)).getOrigin());
String destination = String.valueOf(resultSet.get(2).getDestination());
I just need a pointer as to the best/most efficient/safest way of iterating over all 30 because I am using the results as search test data and need to potentially use each one in turn in a further method which uses the dataset until it gets results back on a website.
I'm continuing to learn JDBI but in the meantime any help would be great
I answered your last question already with a similar answer...you can just adept the code to fit your current case:
for (FlightDataBean i : resultSet){
String startDate = i.getStartDate();
String origin = i.getOrigin();
String destination = i.getDestination();
//further code, go on from here.
}
The for-loop says nothing else, than for every Bean in your resultSet, extract the 3 values (and do the code you added afterwards).
Related
I'm trying to return the record that I got from my database. But I'm having a problem on how I can do that because the data than I retrieved from the database is in a different class from the return parameter.
public List<Record> getRecord(List<Request> requests) {
List<Record> records = new ArrayList<>();
for (Request request : requests) {
Billing billing = billingRepository
.findByBillingCycleAndStartDateAndEndDate(
request.getBillingCycle()
, request.getStartDate()
, request.getEndDate());
if (billing != null) {
// Need to add "billing" to "records" list here
}
}
return records;
}
Record.class
public class Record {
private int billingCycle;
private LocalDate startDate;
private LocalDate endDate;
private String accountName;
private String firstName;
private String lastname;
private double amount;
public Record() {
}
//Getters and setters
Billing.class
public class Billing {
private int billingId;
private int billingCycle;
private String billingMonth;
private Double amount;
private LocalDate startDate;
private LocalDate endDate;
private String lastEdited;
private Account accountId;
public Billing() {
}
//Getters and setters
What can I do? and please explain the answer so I can understand it. I really want to learn
You can use DozerMapper. It will map the object to another object having same name properties or you have to write the mapping in the dozer-mapping xml.
Lets come to your question. Here you are trying to convert your entity to another object.
For that you have to write mapping code. It will be something like this and it is very common practice to convert entity objects to another object before using them.
Record toRecord(Billing billing) {
if(billing == null) {
return null;
}
Record record = new Record();
record.setBillingCycle = billing.getBillingCycle();
...
...
// other properties
...
return record;
}
I have this constructor...
public ShiftLog(String companyName, boolean workedForAgent, String agentName,
Date shiftStart, Date shiftEnd,
boolean breakTaken, Date breakStart,
Date breakEnd, boolean isTransportJob,
String transportCompanyName, String vehicleRegistration) {
this.userUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
this.companyName = companyName;
this.workedForAgent = workedForAgent;
this.agentName = agentName;
this.shiftStart = shiftStart;
this.shiftEnd = shiftEnd;
this.breakTaken = breakTaken;
this.breakStart = breakStart;
this.breakEnd = breakEnd;
this.isTransportJob = isTransportJob;
this.transportCompanyName = transportCompanyName;
this.vehicleRegistration = vehicleRegistration;
}
Now I want to add in a shift log (instantiate a shift log object for a user). The problem is that there are multiple combinations a shift log can have. For example, workedForAgent is false, there should be no need to pass in agentName. How can I do that without creating multiple constructors because there can be multiple possible combinations? For example, user can work for agent but not take a break, meaning break start time and end time shouldn't be needed to pass in. But that would require so many constructors for all possible combinations. Any alternative?
Also I am using the room database to append all this info. So if workedForAgent is false for example, automatically set agentName to null. How could that be done as well.
Take a look at Builder patterns.
Builder pattern is a creational design pattern it means its solves problem related to object creation.
It typically solve problem in object oriented programming i.e determining what constructor to use.
Adding to #Kodiak
You can replace your constructor with builder in few clicks
as mentioned here https://www.jetbrains.com/help/idea/replace-constructor-with-builder.html
Plus, the best part is,it will refactor all the occurrence of the constructor with builder automatically
Short Answer: Use Getters/Setters
Long Answer: The alternative method here is that you can instantiate the variables that you sure they must exist in the constructor and then the other conditional variables can be defined with setter methods and you can easily fetch with getters.
public class ShiftLog {
private Object userUid;
private String companyName;
private boolean workedForAgent;
private String agentName;
private Date shiftStart;
private Date shiftEnd;
private boolean breakTaken;
private Date breakStart;
private Date breakEnd;
private boolean isTransportJob;
private String transportCompanyName;
private String vehicleRegistration;
public ShiftLog(String companyName, Date shiftStart, Date shiftEnd) {
this.userUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
this.companyName = companyName;
this.shiftStart = shiftStart;
this.shiftEnd = shiftEnd;
}
public boolean isWorkedForAgent() {
return workedForAgent;
}
public void setWorkedForAgent(boolean workedForAgent) {
this.workedForAgent = workedForAgent;
}
public String getAgentName() {
return agentName;
}
public void setAgentName(String agentName) {
this.agentName = agentName;
}
public boolean isBreakTaken() {
return breakTaken;
}
public void setBreakTaken(boolean breakTaken) {
this.breakTaken = breakTaken;
}
public Date getBreakStart() {
return breakStart;
}
public void setBreakStart(Date breakStart) {
this.breakStart = breakStart;
}
public Date getBreakEnd() {
return breakEnd;
}
public void setBreakEnd(Date breakEnd) {
this.breakEnd = breakEnd;
}
public boolean isTransportJob() {
return isTransportJob;
}
public void setTransportJob(boolean isTransportJob) {
this.isTransportJob = isTransportJob;
}
public String getTransportCompanyName() {
return transportCompanyName;
}
public void setTransportCompanyName(String transportCompanyName) {
this.transportCompanyName = transportCompanyName;
}
public String getVehicleRegistration() {
return vehicleRegistration;
}
public void setVehicleRegistration(String vehicleRegistration) {
this.vehicleRegistration = vehicleRegistration;
}
}
I am trying to save a base64 value into my sqlite database using Room and for some reason it's not saving. Well, i'm assuming it's not saving because when I try to read the table that has the base64 column, it returns values for all the other columns except the base64 column. What am I doing wrong?
My Entity:
#Entity(tableName = "healthCareWorkerInformation",
foreignKeys = #ForeignKey(
entity = HealthCareWorker.class,
parentColumns = {"id"},
childColumns = {"hcwId"},
onDelete = ForeignKey.CASCADE),
indices = #Index(
value = {"hcwId"}))
public class HealthCareWorkersInformation {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "hcwInfoId")
private long id;
private long hcwId;
//#ColumnInfo(typeAffinity = ColumnInfo.BLOB)
private String base64Image;
private String updatedAt = new SimpleDateFormat("dd MM yyyy, HH:mm",
Locale.getDefault()).format(Calendar.getInstance().getTime());
public HealthCareWorkersInformation() {
}
#Ignore
public HealthCareWorkersInformation(long hcwId) {
this.hcwId = hcwId;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getHcwId() {
return hcwId;
}
public void setHcwId(long hcwId) {
this.hcwId = hcwId;
}
public String getBase64Image() {
return base64Image;
}
public void setBase64Image(String base64Image) {
this.base64Image = base64Image;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(String updatedAt) {
this.updatedAt = updatedAt;
}
}
My DAO:
#Insert
void insertHealthCareWorkerInformation(HealthCareWorkersInformation healthCareWorkersInformation);
#Query("SELECT * FROM HEALTHCAREWORKERINFORMATION")
LiveData<List<HealthCareWorkerInformation>> getHCWInfo();
Sample data I send through:
{"consentGiven":null,"hcwId":1,"patiendId":1,"name":"Ben","lastName":"Ben","dateOfBirth":"4/9/2019","phoneNumber":"+271234567","base64Image":"data:image/png;base64,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"}
Everything else gets saved except for the base64 column. Please assist.
The problem is the semicolon in data:image/png;base64, in combination with " double quotes.
The most easy would be to save the base64 string without that prefix, which breaks the syntax and then assume it is all PNG images (or add a further field, which indicates the encoding of each image).
This problem isn't specific to Room, but specific to Java with SQLite, because that semicolon terminates the statement (which Room will generate). In Java, one can use ' single-quotes only for the primitive data-type char, while the complex data-type String excepts " double-quotes. The only way to get around this limitation, is not trying to save a String containing a ;.
To provide an example of what I mean:
private String base64String = null;
private String base64Type = "png";
public String getBase64Image() {
if(this.base64String != null) {
return "data:image/" + this.base64Type + ";base64," + this.base64String;
} else {
return null;
}
}
I am getting conditionalcheckfailed exception when trying to save/update items using dynamodb mapper.
Can anyone please share snippet of code using java that can demonstrate how versioning and optimistic locking can be implemented successfully?
Tried not setting version at all!!
Tried adding a record to table, and then doing read before save.
Nothing woked!! I continue to get ConditionalCheckFailed Exception.
Only thing works is if I set the config to COBBLER!! but that's not what I want as I need optimistic locking for my data.
DB item class---
#DynamoDBTable(tableName="Funds")
public class FundsItem {
private String id;
private String auditId;
private Long version;
private String shopId;
private String terminalId;
private String txId;
#DynamoDBHashKey(attributeName = "Id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#DynamoDBRangeKey(attributeName = "AuditId")
public String getAuditId() {
return auditId;
}
public void setAuditId(String auditId) {
this.auditId = auditId;
}
#DynamoDBVersionAttribute(attributeName = "Version")
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
#DynamoDBAttribute(attributeName = "ShopId")
public String getShopId() {
return shopId;
}
public void setShopId(String shopId) {
this.shopId = shopId;
}
#DynamoDBAttribute(attributeName = "TerminalId")
public String getTerminalId() { return terminalId; }
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
#DynamoDBAttribute(attributeName = "TxId")
public String getTxId() {
return txId;
}
public void setTxId(String txId) {
this.txId = txId;
}
}
Code to save new item -----
public long addFunds(FundsRequest request){
FundsItem dbItem = new FundsItem();
String Id = request.getShopId().trim() + request.getTerminalId().trim();
String V0_Audit_Rec = "V0_Audit_" + Id;
//save V0 item.
dbItem.setVersion((long) 1);
dbItem.setId(Id);
dbItem.setAuditId(V0_Audit_Rec);
dbItem.setShopId(request.getShopId().trim());
dbItem.setTerminalId(request.getTerminalId().trim());
dbItem.setTxId(request.getTxId().trim());
mapper.save(dbItem);
}
Pls check the snippet above - This is a new empty table.
hashkey - id, rangekey - auditId, VersionField - version.
I just want to be able to add a new record that's why not doing any read before saving a new item. If I can get this simple case i.e. adding a new /first record to the dynamodb table work, I can implement rest of the use cases too.
In general:
Never set your version, the SDK will initialise this if required.
Always try and load an item with your key first. If null is returned, create the item and save it. Else update the returned item and save it.
I know you mentioned you've tried the above. If its truely an empty table your code should work OK (minus the setting of the version).
A couple of things I would also do:
Don't set your version field with a custom attribute name. In theory this should be fine, but for the sake of making your code the same as the AWS examples, I would remove this, at least until you have it working.
Although I think you need to remove the setting of the version, I note you are casting to a long, not a Long. Again, unlikely to be an issue but just something to eliminate at least. i.e. if you insist of setting version use new Long(l).
I have following java class
package com.picvik.model;
import java.util.Date;
public class ViewAlbum {
private Integer albumid;
private String albumname;
private String description;
private String location;
private Date date;
private Integer uid;
public Integer getAlbumid() {
return albumid;
}
public void setAlbumid(Integer albumid) {
this.albumid = albumid;
}
public String getAlbumname() {
return albumname;
}
public void setAlbumname(String albumname) {
this.albumname = albumname;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
}
I am retrieving data from db and adding it to my array list like this
public ArrayList getAllAlbums(Integer uid) {
ViewAlbum album = new ViewAlbum();
ArrayList<ViewAlbum>allAlbums = new ArrayList<ViewAlbum>();
try {
String qstring = "SELECT albumid, albumname, description, location," +
" date, uid FROM picvik_picture_album WHERE " +
"uid = '" + uid + "';";
System.out.println(qstring);
connection = com.picvik.util.MySqlConnection.getInstance().getConnection();
ptmt = connection.prepareStatement(qstring);
resultSet = ptmt.executeQuery();
while(resultSet.next()) {
//System.out.println(resultSet.getString("albumname"));
album.setAlbumid(resultSet.getInt("albumid"));
album.setAlbumname(resultSet.getString("albumname"));
album.setDescription(resultSet.getString("description"));
album.setLocation(resultSet.getString("location"));
album.setDate(resultSet.getDate("date"));
album.setUid(resultSet.getInt("uid"));
allAlbums.add(album);
}
resultSet.close();
ptmt.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
return allAlbums;
}
But when I am trying to print the values stored in array list. Its always giving me the last inserted record.
<div class="row">
<div class="span10">
<s:iterator value="allAlbums">
<s:property value="albumname"/>
</s:iterator>
</div>
</div>
Here,
ViewAlbum album = new ViewAlbum();
// ...
while (resultSet.next()) {
album.setAlbumid(resultSet.getInt("albumid"));
// ...
allAlbums.add(album);
}
you're reusing the very same album instance for all records. The instance's data get overridden everytime in the loop. The list does not contain copies of the instance, but it contains copies of the reference to the single instance. You know, Java is Object Oriented.
You should be creating a new album instance per record. Move the instantiation to inside the loop.
// ...
while (resultSet.next()) {
ViewAlbum album = new ViewAlbum();
album.setAlbumid(resultSet.getInt("albumid"));
// ...
allAlbums.add(album);
}
See also:
How can I pass an Integer class correctly by reference?
Unrelated to the concrete problem, you should be closing JDBC resources in the finally block, or be opening them in the try() try-with-resources statement, otherwise they will still leak away in case of an exception during executing the query or processing the result set. You should also move the declarations of JDBC resources to inside the method block, otherwise you'll run into threadsafety issues as well. Last but not least, you should use the setter methods of PreparedStatement to set user-controlled variables in a SQL string. If they were strings, you'd have a SQL injection attack hole.
See also:
Java Iterator backed by a ResultSet
JDBC MySql connection pooling practices to avoid exhausted connection pool
You have only one instance of ViewAlbum and you are playing(setting the values) only with that single instance throughout the loop. So after completition of loop you have only one object inserted into ArrayList for N(Size of Resultset) no of times.