I have a table with 25 rows and 3-4 columns. I want to use this table once to read all data from it and store it in Java program. Since I will need data frequently throughout my life cycle of Java program, I dont want to connect to DB and execute query. How can I achieve this?
I would create a class with a member that corresponds to the data in the table.
Then I would create some data structure (a map?) by which you can acquire the data.
If you need to have 'database like' access, use an embeded database like Apache Derby. Slurp the data in once from outside, then store it in your local database which will have very responsive lookup times.
Some pseduo-code
Let this class be your binding, for example... I just made stuff up
class MyObject {
private final String key;
private final long stamp;
private final String name;
private final int other;
public MyObject(String key, long stamp, String name, int other) {
this.key = key;
this.stamp = stamp;
this.name = name;
this.other = other;
}
public String toString() {
return name + " has an other of " + other + " and a stamp of " + stamp;
}
}
Your application might look something like this
class MyApp {
Connection con = ... // connect to DB here
// work with DB
ResultSet rs = ... // query the DB for your data
Map<String, MyObject> map = new HashMap<String, MyObject>();
while(rs.next()) {
String key = rs.getString(1);
long stamp = rs.getLong(2);
String name = rs.getString(3);
int other = rs.getInteger(4);
MyObject obj = new MyObject(key,stamp,name,other);
map.put(key,obj);
}
Map<String, MyObject> safeMap = Collections.unmodifiableMap(map);
// spawn 5 threads (yes we should keep ref's to them - oh well
for(int i = 0; i < 5; i++) {
Runnable run = new SomeBackgroundProcess(i,safeMap);
Thread t = new Thread(run);
t.start();
}
}
And a background thread might look something like this
class SomeBackgroundProcess {
final int awesomeNumber;
final Map<String,MyObject> map;
SomeBackgroundProcess(int num, Map<String,MyObject> map) {
this.awesomeNumber = num;
this.map = map;
}
public void run() {
InputStream in = // some input stream, for example
while(true) {
String key = in.magic(); // somehow you acquired a key!
MyObject obj = map.get(key);
if(obj != null) Log.log(obj.toString()); // writes out all about the object it found
}
}
}
if you want to use JTable for display/edit/input/remove some data then you have to
1) first at all read tutorial (all data are allways stored in the TableModel, read this sctions too,)
2) and then go thought ton os examples here and here
3) than if you have a real question how to some..., then don't hesitage to ask question, and in the case that you want from this forum good or better answer, then you have to ... with short and runnable code that shows your issue(s)
You can look up hibernate. It will serve you good as it's used frequently in the industry. You basically provides a properties file with your db info such as server address and credentials and then you make a POJO representing your table and put some annotations on it.
you can use cache concept which holds the data till the user session is lost. Please check below link, there are many examples available google it.
cache concept
Related
I have an object of type ClassTestEvaluation. It holds an ArrayList of type Task. This array can have any number of tasks and is not predictable. I want to set up a table view that will show the given tasks in columns so that the user can enter points.
My problem is that I have no idea how to set an array of variable length that is part of another object as source for my table view. I cannot build a wrapper like ClassTestEvaluationItem with simple members task1, task2, etc. since the number of tasks is not fixed. Thus my question is what do I have to do to properly set the propertyValueFactories for the tasks columns?
I have followed lots of tutorials like the one here: https://docs.oracle.com/javafx/2/ui_controls/table-view.htm. It's generally speaking no problem to follow and get them working. But they only deal with simple (flat) data.
TableView<ClassTestEvaluation> table = new TableView<>();
TableColumn colFirstName = new TableColumn("Vorname");
colFirstName.setCellValueFactory(new PropertyValueFactory<ClassTestEvaluation, String>("firstName");
TableColumn colLastName = new TableColumn("Nachname");
colLastName.setCellValueFactory(new PropertyValueFactory<ClassTestEvaluation, String>("lastName");
table.getColumns().addAll(colFirstName, colLastName);
ArrayList<Task> tasks = classTestEvaluation.getTasks();
for(Task t : tasks) {
TableColumn colTask = new TableColumn(t.getTitle());
table.getColumns().add(colTask);
}
As you can see it's not hard to set PropertyValueFactory for colFirstName and colLastName. But how do I do that for the tasks that are variable in
length and are stored in an array which itself is part of the
ClassTestEvaluation object?
Depending on the number of tasks a classtest has got, I want my table view to look like that:
Firstname | Lastname | Task 1 | Task 2 | ...
I hope someone can help me out here since I don't get it. Thanks a lot!
EDIT 1:
To make my data source a bit more clear, here is the relevant structure of my ClassTestEvaluation and Task classes:
public class ClassTestEvaluation{
// ... more members ...
ArrayList<Task> tasks = ArrayList<>();
public ArrayList<Task> getTasks(){
return this.tasks;
}
// ...more methods...
}
public class Task{
private int id;
private int idClassTestEvaluation;
private Double points;
private String title;
public String getTitle(){
return this.title;
}
public Double getPoints(){ // This methods needs to be connected as data source for tasks cells.
return this.points;
}
// ...more methods...
}
The data comes from an sqlite database, where every task is connected via foreign key to a specific ClassTestEvaluation. When necessary a specific ClassTestEvaluation is constructed and gets populated with the corresponding tasks. Thus I need to find a way to make the tasks (i.e. not only their titles as columns, but also their points as cells) available and editable inside the table view.
Well, I actually found the solution to my own question and thought this might be of interest to others. To recall: my problem was that I didn't know how to built columns out of an array of variable length, which is part of another item (composed).
What I needed to understand is how cellValueFactory, cellFactory and onEditCommit can be used togehter with callbacks or lambdas respectivly to get the desired result. This took me quite a while.
Here is what I did to get it:
private void createTableColumnsForTasks(ClassTestEvaluation cte) {
int resultCounter = 1;
// For each given task in ClassTestEvaluation...
for (Task t : cte.getTasks()) {
// ...create a column for the corresponding points reached (0 in the beginning).
TableColumn<ClassTestEvaluationRow, Double> colResult = new TableColumn<>("A" + resultCounter + " (" + t.getPoints() + ")");
resultCounter++;
// Make the column editable.
colResult.setEditable(true);
// Define how the values in the task columns will be set.
colResult.setCellValueFactory((TableColumn.CellDataFeatures<ClassTestEvaluationRow, Double> row) -> {
ClassTestEvaluationRow cter = row.getValue();
for(Result r : cter.getResults()) {
if(r.getIdTask() == t.getId()) {
ObservableValue<Double> obsResult = new SimpleObjectProperty<Double>(r.getPoints());
return obsResult;
}
}
return null;
});
// Create combo box to choose points from for each given task and result.
createTableColumnComboBoxForResultEditing(colResult, t);
// Create method to store edited data in selected ClassTestEvaluationRow.
createOnEditCommitMethods(colResult, t);
((EvaluatorUI) this.getView()).getTableView().getColumns().add(colResult);
}
}
private void createTableColumnComboBoxForResultEditing(TableColumn<ClassTestEvaluationRow, Double> colResult, Task t) {
ArrayList<Double> cbPoints = new ArrayList<>();
for(double i = 0.0; i <= t.getPoints(); i = i+0.5) {
cbPoints.add(i);
}
ObservableList<Double> obsPoints = FXCollections.observableArrayList(cbPoints);
colResult.setCellFactory(ComboBoxTableCell.<ClassTestEvaluationRow, Double>forTableColumn(obsPoints));
}
private void createOnEditCommitMethods(TableColumn<ClassTestEvaluationRow, Double> colResult, Task t) {
colResult.setOnEditCommit((CellEditEvent<ClassTestEvaluationRow, Double> event) -> {
TablePosition<ClassTestEvaluationRow, Double> pos = event.getTablePosition();
Double newValue = event.getNewValue();
int row = pos.getRow();
ClassTestEvaluationRow cter = (ClassTestEvaluationRow) event.getTableView().getItems().get(row);
for(Result result : cter.getResults()) {
if(result.getIdTask() == t.getId()){
result.setPoints(newValue);
classTestEvaluationsService.updateResult(cter.getClassTestEvaluation(), result);
}
}
});
}
I hope this is of help to some of you. Greetings.
I have this class that serves as a container which I will use the instance variable for processing later
class Data{
static int counter= 0;
boolean boolean1;
String string1;
public Data() {
counter++;
}
}
And I have this method that sets the values of Data
public Data setData()
{
Data data = null;
for (int i = 0; i < somecoutnerhere; i++) {
Data = new Data();
Data.boolean1 = some boolean put here;
Data.string1 = "some string to be put here";
}
return ProcessData(Data);
}
I also have this class ProcessData that will make use of Data and will construct the response
private class ProcessData
{
private final Map<String, List<?>> map = new HashMap<String, List<?>>();
int counter;
public ProcessData(Data data)
{
map.put("boolean1", data.boolean1);
map.put("String1", data.string1);
counter = data.counter;
}
public String someMethodToGenerateReturnData(){
// some code here to make use of the Data collected. Will basically use map to construct the return String
}
}
My problem is that I couldn't figure out how can I return all the instance variables created on the for-loop for Data on setData(). Any thoughts?
My problem is that I couldn't figure out how can I return all the instance variables created on the for-loop for Data on setData(). Any thoughts?
According to this your problem is not "returning all instance one variables in one call", as your title states, but rather a question about how returning all Data-Objects created in your for-loop, which is easier.
Your code is erronous though, so I went ahead & corrected it (I hope I didn't mess up). I also renamed a few things.
The changes I made are:
renamed "boolean1" and "string1" to "trueOrFalse" and "string"
added a public, fully parameterized constructor to the Data-class
added a ProcessData-list to the setData()-method, which is filled in the for-loop
(+ a comment)
However, I'd strongly recommend you to check your architecture, and also to learn a bit about naming conventions, or coding conventions in general. Names should point out the purpose or content of the method/variable/class, and "boolean1" isn't really doing that.
Regarding the architecture: The Data-class seems to exist solely for the counter, and you could easily change that, making the Data-class obsolete (unless it's used somewhere else).
Data class:
class Data {
static int counter = 0;
boolean trueOrFalse;
String string;
public Data() {
counter++;
}
public Data(boolean someBoolean, String someString) {
this.trueOrFalse= someBoolean;
this.string = someString;
counter++;
}
}
setData()-Method:
public List<ProcessData> setData() {
List<ProcessData> processedDataList = new ArrayList<ProcessData>();
for (int i = 0; i < someCounterHere; i++) {
processedDataList.add(new ProcessData(new Data(true, "testString"));
// a new Data-object is created (parameters true and "testString")
// a new ProcessData-object is created (parameter is the newly created Data-Object)
// the newly created ProcessData-object is added to the list
}
return processedDataList;
}
ProcessData-class:
private class ProcessData {
private final Map<String, List<?>> map = new HashMap<String, List<?>>();
int counter;
public ProcessData(Data data) {
map.put("trueOrFalse", data.trueOrFalse);
map.put("string", data.string);
counter = data.counter;
}
public String someMethodToGenerateReturnData() {
// some code here to make use of the Data collected. Will basically use map to construct the return String
}
}
This question is related to this topic : Related jobs in JSprit
I'm trying to use the "one before another" constraint but i'm experiencing a java.lang.IllegalArgumentException: arg must not be null . It looks like Capacity cap2 is null when calculating Capacity max. I don't really understand why.
:(
Do you have an idea about this?
For the record, I'm on the 1.6.2 version. TY for your help.
String before = "2";
String after = "11";
final StateManager stateManager = new StateManager(problem);
stateManager.addStateUpdater(new JobsInRouteMemorizer(stateManager));
ConstraintManager constraintManager = new ConstraintManager(problem, stateManager);
constraintManager.addConstraint(new OneJobBeforeAnother(stateManager, before, after));
final RewardAndPenaltiesThroughSoftConstraints contrib = new RewardAndPenaltiesThroughSoftConstraints(problem, before, after);
SolutionCostCalculator costCalculator = new SolutionCostCalculator() {
#Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.;
List<VehicleRoute> routes = (List<VehicleRoute>) solution.getRoutes();
for(VehicleRoute route : routes){
costs+=route.getVehicle().getType().getVehicleCostParams().fix;
costs+=stateManager.getRouteState(route, InternalStates.COSTS, Double.class);
costs+=contrib.getCosts(route);
}
return costs;
}
};
VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(problem,
"algorithmConfig.xml");
vraBuilder.addCoreConstraints();
vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
vraBuilder.addDefaultCostCalculators();
vraBuilder.setObjectiveFunction(costCalculator);
algorithm = vraBuilder.build();
public class JobsInRouteMemorizer implements StateUpdater, ActivityVisitor {
private StateManager stateManager;
private VehicleRoute route;
public JobsInRouteMemorizer(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
#Override
public void begin(VehicleRoute route) {
this.route=route;
}
#Override
public void visit(TourActivity activity) {
if(activity instanceof JobActivity){
String jobId = ((JobActivity) activity).getJob().getId();
StateId stateId = stateManager.createStateId(jobId);
System.out.println(stateId.getIndex());
System.out.println(stateId.toString());
stateManager.putProblemState(stateId, VehicleRoute.class, this.route);
}
}
#Override
public void finish() {}
}
Short answer: You cannot create StateId instances on the fly. All StateId instances have to be generated before the algorithm is run. See longer answer for why doing this is still not a good idea and you should consider a redesign.
Analysis: I ran into the same problem and traced it back to the way StateId instances are created in StateManager:
public StateId createStateId(String name) {
if (createdStateIds.containsKey(name)) return createdStateIds.get(name);
if (stateIndexCounter >= activityStates[0].length) {
activityStates = new Object[vrp.getNuActivities() + 1][stateIndexCounter + 1];
vehicleDependentActivityStates = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter + 1];
routeStatesArr = new Object[vrp.getNuActivities()+1][stateIndexCounter+1];
vehicleDependentRouteStatesArr = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter+1];
problemStates = new Object[stateIndexCounter+1];
}
StateId id = StateFactory.createId(name, stateIndexCounter);
incStateIndexCounter();
createdStateIds.put(name, id);
return id;
}
Each time you create a new StateId and there is no more space available for states the old state arrays are overwritten with a longer version to make space for your new state (at start there is space for 30 StateIds, a few already used by JSprit itself). As you can see, the old elements aren't copied over, so what happens here is a race condition between UpdateLoads, which sets the state used as cap2, your code, which generates a new StateId and overwrites the current state and UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute which reads the state (that doesn't exist anymore).
Given that this code only extends the arrays by one it is very inefficient to have many StateIds, as for each new StateId all arrays have to be recreated. To mitigate this I used only one StateId in my code and stored a Map<String, VehicleRoute> in it:
Map<String, VehicleRoute> routeMapping = Optional.ofNullable(stateManager.getProblemState(stateId, Map.class)).orElse(new ConcurrentHashMap<>())
This way you don't run out of StateId instances and can still store relations between an unlimited number of jobs.
I don't know if this is possible in Java but I was wondering if it is possible to use an object in Java to return multiple values without using a class.
Normally when I want to do this in Java I would use the following
public class myScript {
public static void main(String[] args) {
// initialize object class
cl_Object lo_Object = new cl_Object(0, null);
// populate object with data
lo_Object = lo_Object.create(1, "test01");
System.out.println(lo_Object.cl_idno + " - " + lo_Object.cl_desc);
//
// code to utilize data here
//
// populate object with different data
lo_Object = lo_Object.create(2, "test02");
System.out.println(lo_Object.cl_idno + " - " + lo_Object.cl_desc);
//
// code to utilize data here
//
}
}
// the way I would like to use (even though it's terrible)
class cl_Object {
int cl_idno = 0;
String cl_desc = null;
String cl_var01 = null;
String cl_var02 = null;
public cl_Object(int lv_idno, String lv_desc) {
cl_idno = lv_idno;
cl_desc = lv_desc;
cl_var01 = "var 01";
cl_var02 = "var 02";
}
public cl_Object create(int lv_idno, String lv_desc) {
cl_Object lo_Object = new cl_Object(lv_idno, lv_desc);
return lo_Object;
}
}
// the way I don't really like using because they get terribly long
class Example {
int idno = 0;
String desc = null;
String var01 = null;
String var02 = null;
public void set(int idno, String desc) {
this.idno = idno;
this.desc = desc;
var01 = "var 01";
var02 = "var 02";
}
public int idno() {
return idno;
}
public String desc() {
return desc;
}
public String var01() {
return var01;
}
public String var02() {
return var02;
}
}
Which seems like a lot of work considering in Javascript (I know they are different) I can achieve the same effect just doing
var lo_Object = f_Object();
console.log(lo_Object["idno"] + " - " + lo_Object[desc]);
function f_Object() {
var lo_Object = {};
lo_Object = {};
lo_Object["idno"] = 1;
lo_Object["desc"] = "test01";
return lo_Object;
}
NOTE
I know the naming convention is wrong but it is intentional because I have an informix-4gl program that runs with this program so the coding standards are from the company I work for
The best way to do this is to use HashMap<String, Object>
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Object> person =
new HashMap<String, Object>();
// add elements dynamically
person.put("name", "Lem");
person.put("age", 46);
person.put("gender", 'M');
// prints the name value
System.out.println(person.get("name"));
// asures that age element is of integer type before
// printing
System.out.println((int)person.get("age"));
// prints the gender value
System.out.println(person.get("gender"));
// prints the person object {gender=M, name=Lem, age=46}
System.out.println(person);
}
}
The advantage of doing this is that you can add elements as you go.
The downside of this is that you will lose type safety like in the case of the age. Making sure that age is always an integer has a cost. So to avoid this cost just use a class.
No, there is no such a feature, you have to type out the full type name(class name).
Or use may use val :
https://projectlombok.org/features/val.html
Also, if you use IntelliJ IDEA
try this plugin :
https://bitbucket.org/balpha/varsity/wiki/Home
I am not sure if it's possible with Java. Class is the primitive structure to generate Object. We need a Class to generate object. So, for the above code, i don't think there is a solution.
Java methods only allow one return value. If you want to return multiple objects/values consider returning one of the collections. Map, List, Queue, etc.
The one you choose will depend on your needs. For example, if you want to store your values as key-value pairs use a Map. If you just want to store values sequentially, use a list.
An example with a list:
list<Object> myList = new ArrayList<Object>();
myList.add("Some value");
return myList;
As a side note, your method create is redundant. You should use getters and setters to populate the object, or populate it through the constructor.
cl_Object lo_Object = new cl_Object(1, "test01");
The way you have it set up right now, you're creating one object to create another of the same type that has the values you want.
Your naming convention is also wrong. Please refer to Java standard naming convention:
http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html#367
I have a code in which each thread will work for 10 minutes and it will decide which table I am supposed to pick basis on random number. And then after that I am executing a SQL query for that table using PreparedStatement. After executing it, I need to loop through the result set only if the data is there in the ResultSet and add the data in List<String> colData.
Here columnsList will contains table columns delimited by comma. For example-
col1, col2, col3
Below is the code-
class ReadTask implements Runnable {
private static Random random = new SecureRandom();
public ReadTask() {
}
#Override
public run() {
...
while ( < 10 minutes) {
double randomNumber = random.nextDouble() * 100.0;
ReadTableConnectionInfo tableInfo = selectRandomConnection(randomNumber);
final int id = generateRandomId(random);
final String columnsList = getColumns(table.getColumns());
final String selectSql = "SELECT " + columnsList + " from " + table.getTableName() + " where id = ?";
preparedStatement = tableStatement.get(table.getTableName()).prepareCall(selectSql);
preparedStatement.setString(1, String.valueOf(id));
rs = preparedStatement.executeQuery();
List<String> colData = new ArrayList<String>(columnsList.split(",").length);
boolean foundData = false;
if (id >= 1 && id <= 5000) {
if (rs.next()) {
foundData = true;
for (String column : columnsList.split(",")) {
colData.add(rs.getString(column));
}
rs.next();//this should return false or an error condition and do I need this here?
}
} else if (rs.next()) {
// do some stuff
}
if (flagValidateData && foundData) {
// iterate through colData map
}
}
}
}
Problem Statement:-
1) Do I need synchronization on my colData list or not?
2) Whether the way I am add the data in List<String> colData is thread safe or not?
3) And is there any other problem in the way I am looping through the result set and adding it to colData string array? As given that, its a Multithreaded code, so it will be hard to debug it out for any race conditions.
Whether the add method is multi-thread safe depends on the implementing class. ArrayList is not multi-thread safe. Vector is synchronized, or you can wrap an ArrayList using the Collections.synchronizedList method.
You can make any List thread safe like this:
List<String> names = new ArrayList<String>(); // not thread safe
List<String> threadSafeNames = Collections.synchronizedList(names);
A better solution might be a new data structure from java.util.concurrent, like CopyOnWriteArrayList.
if you need synchronized data, why don't you write a synchronized read- and write function?
also collections and lists can be synchronyzed, if you extend them
my mother's tounge is german (aut/vie) and it's 3... ;)
sync is used where data can be overwritten or replaced by multiple access
if you got something in sync, it can brake your system out (speeding down)
cuz:
sync means, that only one object can handle some section
if you had an thread witch access some method, the next thread MUST wait until the thread before is finished with the section
a good example:
writing data to a single file using streams and write some data to the file or output-connect:
public synchronized void write(OutputStream str, byte toSend[]){...}
i usaly use synchronized for pool-techniques, such as get-next-operation (list-removal, return last element)
im tired of 18 hours of work ;)
i just say:
whatever you have to sync, write a function for it
e.g.
public synchronized void colData_add(final String str) // or object or whatever
{
...
}
public synchronized String colData_nextElement()
{
return colData.remove();
}
hope this helpz