I am working on an example using FilteredRowSet, I am trying to run a query, then filter the results using the Predicate object.
Here is my code:
import javax.sql.rowset.FilteredRowSet;
import oracle.jdbc.rowset.OracleFilteredRowSet;
public class Example {
public static void main(String[] args) throws SQLException,
IOException {
try (FilteredRowSet rs = new OracleFilteredRowSet();) {
rs.setUrl("jdbc:oracle:thin:#localhost:1521:xe");
rs.setUsername("dbuser");
rs.setPassword("dbpassword");
rs.setCommand("select * from employees");
rs.execute();
String name[] = {"user1", "user2"};
rs.setFilter(new UserFilter("lastname", name));
while(rs.next()){
String lname= rs.getString("lastName");
System.out.println(lname);
}
}
}
}
Here is my Predicate class:
import javax.sql.RowSet;
import javax.sql.rowset.Predicate;
public class UserFilter implements Predicate {
private String[] names;
private String colName = null;
public UserFilter(String colName, String[] names) {
this.names = names;
this.colName = colName;
}
#Override
public boolean evaluate(RowSet arg0) {
return false;
}
#Override
public boolean evaluate(Object arg0, int arg1) throws SQLException {
return false;
}
#Override
public boolean evaluate(Object valueArg, String colNameArg) throws SQLException {
if (colNameArg.equalsIgnoreCase(this.colName)) {
for (int i = 0; i < this.names.length; i++) {
if (this.names[i].equalsIgnoreCase((String) valueArg)) {
return true;
}
}
}
return false;
}
}
In my database table employees I have records with lastName as values user1 and user2 but when I apply the filter as shown in my question, I am not getting any output. I mean the code is not entering the while loop.
Can you please tell me how to apply the filter? I am expecting the output contains the records whose lastName contains user1 or user2
You have to implement the logic of
public boolean evaluate(RowSet arg0);
As a best practice, your filter should implement the 3 evaluate() methods.
In order to avoid code redundancy in these 3 methods, you can create a private helper method that contains the actual logic of comparing the col/row value with the ones from the filter, and have the 3 evaluate() methods call it. For an example look at this filter, that do not factorise the code logic tough.
Related
I try to compare different types with hamcrest. But I don't understand, how I have to build my own Matcher for the following problem:
String[] exp = new String[]{"x", "y", "z"};
DAO[] cur = getFromExternalWebservice();
Assert.assertThat("wrong strings", exp, Matchers.arrayContainingInAnyOrder(cur));
cur is an array of the following class:
class DAO {
public String id;
public String name;
}
The test above should actually compare the Strings within exp and the name property of the DAO objects within the array cur. I cannot change something on DAO (like adding a toString() method).
I can transform the results from the webservice into a names array, which I send to the Matcher like this:
String names[] = new String[cur.length];
for (int i = 0; i < cur.length; i++) {
names[i] = cur[i].name;
}
Assert.assertThat("wrong strings", exp, Matchers.arrayContainingInAnyOrder(names));
But this is ugly, how I can build a Matcher which compares the Strings without any copy of data?
I have implemented a first idea:
public class IsIn extends BaseMatcher<String> {
class DAOIterator implements Iterable<String>, Iterator<String> {
private final DAO[] collection;
private int idx;
public DAOIterator(DAO[] elements) {
this.collection = elements;
idx = 0;
}
#Override
public boolean hasNext() {
return (this.collection.length > this.idx);
}
#Override
public String next() {
return this.collection[this.idx++].name;
}
#Override
public Iterator<String> iterator() {
return new DAOIterator(this.collection);
}
}
private final DAO[] collection;
public IsIn(DAO[] elements) {
this.collection = elements;
}
#Override
public boolean matches(Object o) {
for (DAO d : this.collection) {
if (o == null ? d.name == null : o.equals(d.name)) {
return true;
}
}
return false;
}
#Override
public void describeTo(Description buffer) {
buffer.appendText("one of ");
buffer.appendValueList("{", ", ", "}", new DAOIterator(this.collection));
}
}
Call this on JUnit testcase:
String[] exp = new String[]{"x", "y", "z"};
DAO[] cur = getFromExternalWebservice();
Assert.assertThat("wrong strings", Arrays.asList(exp), Matchers.everyItem(new IsIn(cur)));
I already filtered a group of object against a specific string entered in the EditText and now I need to sort that list with the position of the specified string, how can I do that?
I am already done this
Filter Function
public void setFilter(String query) {
visibleList = new ArrayList<>();
query = query.toLowerCase(Locale.getDefault());
for (AccountProfile accountProfile : accountProfileList) {
if (accountProfile.getName().toLowerCase(Locale.getDefault())
.contains(query))
visibleList.add(accountProfile);
}
Collections.sort(visibleList, new AccountNameComparator());
}
AccountNameComparator
public class AccountNameComparator implements Comparator<AccountProfile> {
#Override
public int compare(AccountProfile first, AccountProfile second) {
return first.getName().compareTo(second.getName());
}
}
the list is sorted but it is based on the getname() I need to sort the list with specific substring of the getname()
To sort that list with the position of the specified string, you could try something like this:
public class AccountNameComparator implements Comparator<AccountProfile> {
private final String query;
public AccountNameComparator(String query) {
this.query = query;
}
#Override
public int compare(AccountProfile first, AccountProfile second) {
Integer f = first.getName().indexOf(this.query);
Integer s = second.getName().indexOf(this.query);
return f.compareTo(s);
}
}
There is slight change in above answer: like below
public class AccountNameComparator implements Comparator<AccountProfile> {
private final String query;
public AccoluntNameSortComparator(String query) {
this.query = query;
}
#Override
public int compare(AccountProfile first, AccountProfile second) {
String firstName = first.getName().toLowerCase();
String secoundName = second.getName().toLowerCase();
query = query.toLowerCase();
Integer f = firstName.indexOf(query);
Integer s = secoundName.indexOf(query);
return f.compareTo(s);
}
}
I have a datagrid in GWT, and I'm using RPC to populate it with data, I can get the data to show up just fine, and I can also select individual cells but when it comes to sorting it just doesn't work! I can occasionaly click on column headers (it happens intermittently and I'm not sure why) but when I do nothing sorts. I'm using a dataProvider, but I think I'm implementing it incorrectly, I've attached the related code, can someone give me a pointer on how to do this correctly?
first is the actual table itself
public class GuiInventory {
public final static LayoutPanel hpMain = new LayoutPanel();
static ListHandler<OpInventory> sortHandler;
/*
* Define a key provider for a Contact. We use the unique ID as the key,
* which allows to maintain selection even if the name changes.
*/
static ProvidesKey<OpInventory> keyProvider = new ProvidesKey<OpInventory>() {
#Override
public Object getKey(OpInventory item) {
// Always do a null check.
return (item == null) ? null : item.getPartID();
}
};
//the table
final static DataGrid<OpInventory> table = new DataGrid<OpInventory>(keyProvider);
final static SelectionModel<OpInventory> selectionModel = new MultiSelectionModel<OpInventory>(keyProvider);
/**
* The provider that holds the list of contacts in the database.
*/
private final static ListDataProvider<OpInventory> dataProvider = new ListDataProvider<OpInventory>();
public ListDataProvider<OpInventory> getDataProvider() {
return dataProvider;
}
/**
* Add a display to the database. The current range of interest of the display
* will be populated with data.
*
* #param display a {#Link HasData}.
*/
public void addDataDisplay(HasData<OpInventory> display) {
dataProvider.addDataDisplay(display);
}
/**
* Refresh all displays.
*/
public void refreshDisplays() {
dataProvider.refresh();
}
public static Widget init() {
hpMain.clear();
table.setWidth("100%");
table.setSelectionModel(selectionModel);
Ioma.dataservice.getPartInventory(new AsyncCallback<ArrayList<OpInventory>>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(ArrayList<OpInventory> result) {
dataProvider.setList(result);
// Attach a column sort handler to the ListDataProvider to sort the list.
sortHandler = new ListHandler<OpInventory>(result);
table.addColumnSortHandler(sortHandler);
dataProvider.addDataDisplay(table);
if (table.getColumnCount() == 0) {
initTable();
}
}
});
//add in table
hpMain.add(table);
return hpMain;
}
public static void initTable() {
// Add a text column to show the part ID.
Column<OpInventory, Number> partIDColumn = new Column<OpInventory, Number>(new NumberCell()) {
#Override
public Integer getValue(OpInventory object) {
return object.getPartID();
}
};
table.addColumn(partIDColumn, "Part ID");
table.setColumnWidth(partIDColumn, 4, Unit.PX);
//add a sort to partID
partIDColumn.setSortable(true);
sortHandler.setComparator(partIDColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return Integer.valueOf(o1.getPartID()).compareTo(o2.getPartID());
}
});
// Add a text column to show the part Number.
Column<OpInventory, String> partNumberColumn = new Column<OpInventory, String>(new EditTextCell()) {
#Override
public String getValue(OpInventory object) {
return object.getPartNumber();
}
};
table.addColumn(partNumberColumn, "Part Number");
table.setColumnWidth(partNumberColumn, 4, Unit.PX);
//add a sort to the part Number
partNumberColumn.setSortable(true);
sortHandler.setComparator(partNumberColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return o1.getPartNumber().compareTo(o2.getPartNumber());
}
});
//add a field updater to be notified when the user enters a new Part Number
partNumberColumn.setFieldUpdater(new FieldUpdater<OpInventory, String>() {
#Override
public void update(int index, OpInventory object, String value) {
object.setPartNumber(value);
//TODO add async call to database to update part Number
table.redraw();
}
});
// Add a text column to show the name.
Column<OpInventory, String> nameColumn = new Column<OpInventory, String>(new EditTextCell()) {
#Override
public String getValue(OpInventory object) {
return object.getName();
}
};
table.addColumn(nameColumn, "Name");
table.setColumnWidth(nameColumn, 10, Unit.PX);
//add a field updater to be notified when the user enters a new part name
nameColumn.setFieldUpdater(new FieldUpdater<OpInventory, String>() {
#Override
public void update(int index, OpInventory object, String value) {
object.setName(value);
//TODO add async call to database to update part name
table.redraw();
}
});
//add a sort to the name
nameColumn.setSortable(true);
sortHandler.setComparator(nameColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return o1.getName().compareTo(o2.getName());
}
});
}
this is the Opinventory class to hold each object in the datagrid
public class OpInventory implements Comparable<OpInventory>, IsSerializable {
int partID;
String partNumber;
String name;
String desc;
String partLotNumber;
String supplier;
String reOrderNumber;
boolean isActive;
int quantity;
Double price;
/**
* The key provider that provides the unique ID of a contact.
*/
public static final ProvidesKey<OpInventory> KEY_PROVIDER = new ProvidesKey<OpInventory>() {
#Override
public Object getKey(OpInventory item) {
return item == null ? null : item.getPartID();
}
};
#Override
public int compareTo(OpInventory o) {
return (o == null || o.partNumber == null) ? -1 : -o.partNumber.compareTo(partNumber);
}
#Override
public boolean equals(Object o) {
if (o instanceof OpInventory) {
return partID == ((OpInventory) o).partID;
}
return false;
}
#Override
public int hashCode() {
return partID;
}
public OpInventory(int partID, String partNumber, String name, String desc, String partLotNumber, String supplier, String reOrderNumber, Double price, boolean isActive) {
this.partID = partID;
this.partNumber = partNumber;
this.name = name;
this.desc = desc;
this.partLotNumber = partLotNumber;
this.supplier = supplier;
this.reOrderNumber = reOrderNumber;
this.price = price;
this.isActive = isActive;
}
public OpInventory() {
}
//getters and setters here
}
Apparently my issue was with the fact that I had a keyProvider in both classes, instead of just one. I removed it from the OpInventory class and it seems to work now. this looks like a very specific issue so I expect this question will be closed soon. but I'll leave the code there for future analysis.
I have a simple loop that checks for any duplicate results,
where studresults holds my results , result is the object result given to the method and r is the current object from the array.
I have been using this method successfully throughout the program although it is not working in this case even though when I debug result and r , are exactly the same does anyone know why this might be? I have tried #Override already as suggested in other answers to no avail.
I am trying to stop duplicated array elements by throwing an exception.
for(Result r : studresults)
{
if(r.equals(result))
{
return false;
}
}
EDIT OK HERE IS THE WHOLE CLASS>
package ams.model;
import java.util.ArrayList;
import java.util.Arrays;
import ams.model.exception.EnrollmentException;
public abstract class AbstractStudent implements Student {
private int studentId;
private String studentName;
private ArrayList<Course> studcourses = new ArrayList<Course>();
private ArrayList<Result> studresults = new ArrayList<Result>();
public AbstractStudent(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
}
public String getFullName() {
return studentName;
}
public int getStudentId() {
return studentId;
}
public Result[] getResults() {
Result[] res = studresults.toArray(new Result[0]);
if(res.length > 0 )
{
return res;
}
return null;
}
public boolean addResult(Result result)
{
for(Result r : studresults)
{
if(r.equals(result))
{
return false;
}
}
studresults.add(result);
return true;
}
public void enrollIntoCourse(Course c)
{
//for re-enrollment
if(studcourses.contains(c))
{
studcourses.remove(c);
studresults.clear();
}
studcourses.add(c);
}
public void withdrawFromCourse(Course c) throws EnrollmentException
{
if(studcourses.size() > 0)
{
studcourses.remove(c);
}
else
throw new EnrollmentException();
}
public Course[] getCurrentEnrolment()
{
return studcourses.toArray(new Course[0]);
}
public abstract int calculateCurrentLoad();
public int calculateCareerPoints() {
// TODO Auto-generated method stub
return 0;
}
public String toString()
{
return studentId + ":" + studentName +":" + calculateCurrentLoad();
}
}
Do you already override hashCode method in Result?
If you override equals, you have to override the hashCode method also to allow you return the same hashcode for the similar objects (objects which has the same value but actually different object instances).
I think the default implementation of hashcode will returns different value for a different object instances even though they have the same values.
Instead I converted toString and then compared and it works???
Makes me think there was something slightly unidentical before?
New method
public boolean addResult(Result r)
{
for (Result s : studresults)
{
String sr1 = s.toString();
String sr2 = r.toString();
if(sr1.equals(sr2))
{
return false;
}
}
I want to create a library(Jar file) in Java which would contain all my methods for the database we use. There are about 60 methods in there so I would like to make it more organized. I would like to call the methods like the example provided below.
db.accounts.add(username, password); or db.accounts().add(username, password);
db.names.delete(name); or db.names().delete(name);
What is the best way of doing this in Java?
You could save yourself a lot of trouble and write a generic DAO:
package persistence;
public interface GenericDao<K, V> {
V find(K id);
List<V> find();
K save(V value);
void update(V value);
void delete(V value);
}
I'd forget about writing your own persistence classes and use a proven solution, like Spring JDBC template.
This problem has been solved many times, many ways. What do you hope to do to improve upon what exists? How will you justify the added expense of developing, testing, and maintaining this functionality?
Here some snapshot of my custom library for connect to database:
PostgreConnection.java
public class PostgreConnection {
private static Connection conn;
public Connection makeConnection(String url, String db, String username, String password) {
if (conn == null) {
try {
Class.forName(Constants.POSTGRES_DRIVER);
conn = DriverManager.getConnection(Constants.POSTGRES_URL + url + "/" + db, username, password);
} catch (SQLException | ClassNotFoundException ex) {
Logger.getLogger(PostgreConnection.class.getName()).log(Level.SEVERE, null, ex);
}
}
return conn;
}
}
Constants.java
public class Constants {
public static String POSTGRES_URL = "jdbc:postgresql://";
public static String POSTGRES_DRIVER = "org.postgresql.Driver";
}
In org.ert.model you can store all the Model that you need based on the tables of your database.
NotifyCharts.java
public class NotifyCharts {
private Integer Id;
private String revName;
private Date importDate;
private Integer pages;
private Boolean status;
public Integer getId() {
return Id;
}
public void setId(Integer Id) {
this.Id = Id;
}
public Date getImportDate() {
return importDate;
}
public void setImportDate(Date importDate) {
this.importDate = importDate;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public String getRevName() {
return revName;
}
public void setRevName(String revName) {
this.revName = revName;
}
public Boolean isStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
}
SQLQuery is an abstract class for some basic method such as insert, update, delete, etc.
SQLQuery.java
public abstract class SQLQuery<T> {
protected void makeStatement(String url, String db, String username, String password) {
PostgreConnection connect = new PostgreConnection();
Connection con = connect.makeConnection(url, db, username, password);
try {
state = (Statement) con.createStatement();
} catch (SQLException ex) {
Logger.getLogger(SQLQuery.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String arrayBuilder(Object[] obj, boolean val) {
StringBuilder arr = new StringBuilder();
arr.append("(");
for (int i = 0; i < obj.length; i++) {
if (i < obj.length - 1) {
if (val) {
arr.append("'");
}
arr.append(obj[i]);
if (val) {
arr.append("'");
}
arr.append(", ");
} else {
if (val) {
arr.append("'");
}
arr.append(obj[i]);
if (val) {
arr.append("'");
}
}
}
arr.append(")");
return arr.toString();
}
public int insertRecord() throws SQLException {
StringBuilder query = new StringBuilder();
query.append("INSERT INTO ").append(tableName).append(arrayBuilder(columns, false)).append(" VALUES ").append(arrayBuilder(values, true));
return state.executeUpdate(query.toString());
}
public ResultSet getAll() throws SQLException {
StringBuilder query = new StringBuilder();
query.append("SELECT * FROM ").append(tableName);
rSet = state.executeQuery(query.toString());
return rSet;
}
public abstract void setColsAndVals(T t);
}
NotifyChartsSQL.java is implementation of the abstract class, org.ert.sql.impl is package to store all your implementation that you need.
NotifyChartsSQL.java
public class NotifyChartsSQL extends SQLQuery<NotifyCharts> {
public NotifyChartsSQL(String url, String db, String username, String password, NotifyCharts notify) {
makeStatement(url, db, username, password);
setColsAndVals(notify);
}
#Override
public final void setColsAndVals(NotifyCharts notify) {
Map<String, Object> objects = new HashMap<>();
String[] columns;
Object[] values;
if(notify.getId() != null)
objects.put("id", notify.getId());
if(notify.getRevName() != null)
objects.put("rev_name", notify.getRevName());
if(notify.getImportDate() != null)
objects.put("import_date", notify.getImportDate());
if(notify.getPages() != null)
objects.put("pages", notify.getPages());
objects.put("status", notify.isStatus());
columns = Arrays.copyOf(objects.keySet().toArray(), objects.size(), String[].class);
values = objects.values().toArray();
setColumns(columns);
setValues(values);
setTableName("notify_charts");
}
}
And last is the test package that test your custom library to make sure that everything is ok.
TestMain.java
public class TestMain {
public static void main(String[] args) {
NotifyCharts notify = new NotifyCharts();
try {
notify.setRevName("Test456");
notify.setImportDate(new Date());
notify.setPages(10);
notify.setStatus(false);
NotifyChartsSQL notCharts = new NotifyChartsSQL("localhost:5432", "charts", "username", "password", notify);
int status = notCharts.insertRecord();
if (status == 1) {
System.out.println("Success Insert");
} else {
System.out.println("Failed Insert");
}
} catch (SQLException ex) {
Logger.getLogger(TestMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I suggest if you want to make this custom library if you using manual JDBC and not using ORM such as Hibernate. Because in Hibernate is already provide all the methods that you need except do you want to add some special method you can do like duffymo said before. This idea of custom library is come from the DAO and the Hibernate structure.
Thanks for read it, and please learn some Design Pattern in Java if you want to make some custom library that more organized.