I have created web service in JAVA Netbeans and called MySQL data through rest web service.
Edited code:
For loop shows all areas in sorting order then why as json output all data are not displayed in ascending order???
my method is as follows :
#GET
#Path("/ShowAreasDup")
#Produces(MediaType.APPLICATION_JSON)
public List<EntityAreas> ShowAreasDup(){
ArrayList<EntityAreas> listSort;
try{
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection(DB_URL,USER,PASSWORD);
String query = "SELECT * FROM Areas ORDER BY AreaName";
Statement statement = conn.createStatement();
ResultSet resultset = statement.executeQuery(query);
// iterate through the java resultset
while (resultset.next())
{
int id = resultset.getInt("AreaID");
String restroName = resultset.getString("AreaName");
EntityAreas anames=new EntityAreas();
anames.setAreaid(id);
anames.setAreaname(restroName);
ShowentityAreas.put(id, anames);
}
statement.close();
}
catch(HeadlessException | SQLException |ClassNotFoundException ee)
{
JOptionPane.showMessageDialog(null, ee);
}
listSort=new ArrayList<EntityAreas>(ShowentityAreas.values());
Collections.sort(listSort,new Comparator<EntityAreas>(){
#Override
public int compare(EntityAreas o1, EntityAreas o2) {
return o1.getAreaname().compareTo(o2.getAreaname());
}
});
for(EntityAreas entityarea:listSort){
System.out.println(entityarea);
}
return listSort;
}
thank you in advance for help
Edit :
Above code is works perfectly for me
thanks to all for giving me a direction to the answser :)
Given your code, there could be some hypothesis. The most probable is that ShowAreas stores the information in an non ordered data structure (for example an HashMap).
If you want to maintain your values in order , you have to use some additional data structure. For example, you can use a TreeSet for the values.
Another solution could be to sort the values immediatly before returning them (javadoc),
// Get the elements
List<Areas> areas = new ArrayList<Areas>(ShowAreas.values());
// Sort them
Collections.sort(areas);
// Return them
return areas;
Pay attention: if you want to use this method, the class Areas must implement Comparable.
A last advise: don't put the code that interacts with the database in the class that has the responsibility to receive external REST calls. You violates the single responsibility principle and your application will become unmaintainable very quickly. Try to use a structure Controller - Service - Repository.
Related
I have this paging problem where when I try to sort a table by field header on a particular page number, PageRequest.of(page-1, 10, sort) is sorting the entire table, not on a particular page. Thus, what record is returned in that page is different from the previous record before sorting.
Code:
#Override
public Page<User> getPageAndSort(String field, String direction, int page) {
Sort sort = direction.equalsIgnoreCase(Sort.Direction.ASC.name())
? Sort.by(field).ascending()
: Sort.by(field).descending();
Pageable pageable = PageRequest.of(page-1, 10, sort);
return userRepo.findAll(pageable);
}
For example. I want to sort only in page 1 by id. Returning a sorted record from page 1. The rest of the pages or entire records shouldn't
be affected.
Thank you.
Edit:
I have a workaround in this problem. After getting a page from:
Page<User> page = userService.findPage(currentPage);
I get the page.getContent() List and then pass to method sortList:
userService.sortList(new ArrayList<>(page.getContent()), field, sortDir)
sort implementation:
public ArrayList<User> sortList(ArrayList<User> users, String field, String direction) {
users.sort((User user1, User user2) -> {
try {
Field field1 = user1.getClass().getDeclaredField(field);
field1.setAccessible(true);
Object object1 = field1.get(user1);
Field field2 = user2.getClass().getDeclaredField(field);
field2.setAccessible(true);
Object object2 = field2.get(user2);
int result = 0;
if (isInt(object1.toString())) {
result = Integer.parseInt(object1.toString()) - Integer.parseInt(object2.toString());
} else {
result = object1.toString().compareToIgnoreCase(object2.toString());
}
if (result > 0) {
return direction.equalsIgnoreCase("asc") ? 1 : -1;
}
if (result < 0) {
return direction.equalsIgnoreCase("asc") ? -1 : 1;
}
return 0;
} catch (Exception e) {
Log.error(e.toString());
return 0;
}
});
return users;
}
With this work around. I successfully sorted a particular page by its column header without affecting the rest of pages. But it's not standard though as it doesn't use PageRequest.of() from Spring Data JPA and I recommend testing the code and review it thoroughly.
I think an if condition could solve the problem. Create Pageable instance with respect to the condition.
#Override
public Page<User> getPageAndSort(String field, String direction, int page) {
Sort sort = direction.equalsIgnoreCase(Sort.Direction.ASC.name())
? Sort.by(field).ascending()
: Sort.by(field).descending();
Pageable pageable = (page == 1)?PageRequest.of(page-1, 10, sort)
:PageRequest.of(page-1, 10);
return userRepo.findAll(pageable);
}
References : https://www.baeldung.com/spring-data-jpa-pagination-sorting#:~:text=We%20can%20create%20a%20PageRequest%20object%20by%20passing,%280%2C%202%29%3B%20Pageable%20secondPageWithFiveElements%20%3D%20PageRequest.of%20%281%2C%205%29%3B
I think this helps.
I don't think there is an easy way to make this kind of sorting in the database and since you are dealing with a single page which is memory anyway since you render it to the UI, I would just sort it in memory.
Alternatively you can go with a custom SQL statement structured like this:
SELECT * FROM (
SELECT * FROM WHATEVER
ORDER BY -- sort clause defining the pagination
OFFSET ... LIMIT ... -- note that this clause is database dependent.
) ORDER BY -- your sort criteria within the page goes here
You'll have to construct this SQL statement programmatically, so you can't use Spring Datas special features like annotated queries or query derivation.
I'm not sure, I got your question, but if you want a certain sorted page, the db should definitely create the query plan, sort all the data and return you a certain offset (Page) of the sorted data.
It's impossible to get a sorted page without sorting the whole data.
I believe you want to sort data only on a given page, this is difficult to manage with database query which probably will sort whole data and would give you nth page.
I would suggest to do a reverse on a given page after retrieving with same order.
Retrieve the nth page with from database with always asc.
Depending on direction do a reverse if needed.
This should be faster than relying on database for sort operation.
I am trying to make an app which import data from database and use it in another function.
I got connection with database and it returns me a variable called miejsce:
public void sprawdzAuto(String nrRej, String miejsce){
try{
String query = "select lokalizacja from samochody75 where nrRej=?";
PreparedStatement pst = con.prepareStatement(query);
pst.setString(1, nrRej);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
miejsce = rs.getString(1);
System.out.println(miejsce);
}
JOptionPane.showMessageDialog(null, "Znaleziono.");
} catch(SQLException e) {
System.out.print(e);
}
}
Now when i got miejsce i want to use it in another .java file called Mapa.
public class Mapa extends MapView{
private Map map;
public Mapa(String nName)
{
JFrame frame = new JFrame(nName);
setOnMapReadyHandler(new MapReadyHandler() {
#Override
public void onMapReady(MapStatus status) {
if (status == MapStatus.MAP_STATUS_OK){
map=getMap();
MapOptions mapOptions = new MapOptions();
MapTypeControlOptions controlOptions= new MapTypeControlOptions();
mapOptions.setMapTypeControlOptions(controlOptions);
map.setOptions(mapOptions);
map.setCenter(new LatLng(1,1));
map.setZoom(17.0);
Marker mark = new Marker(map);
mark.setPosition(map.getCenter());
}
}
});
frame.add(this, BorderLayout.CENTER);
frame.setSize(700,500);
frame.setVisible(true);
}
}
I want result of miejsce to map.setCenter();
I tried diffrent things but none of them works.
Is there any solution to make it possible?
Thank you in advance.
You seem to missunderstand a lot of concepts about how scope and Java in general works. You should try and find a java tutorial before posting on StackOverflow.
Here are some tips that can help you in your problem.
You are iterating through a ResultSet which means you probably won't have only one result. So when you write miejsce = rs.getString(1); only the last value of your result set will be stored in your string.
String is an immutable object. Which means that when you pass a String as a parameter to a method, you will not be able to access the value of your String from the calling method unless you return it from the called method. And that's not what you are doing here.
To complete my two previous points and to solve partially yours, you can take a look at List in java. Where you can store objects and values, strings included, and you will be able to access the content of your list, filled from the called method (sprawdzAuto here), from your calling method.
I won't do the code for you, I think it is better if you do some digging yourself.
Hope this helps.
What I currently have done: Since I am using aws lambda and aws API Gateway, I have learned to capture specific parts of the URI such as the Path and the queryParameters, and I am building different queries to my database based on the path and parameter given.
Example:
https://ApiURI/user?id=id_1
Path=User
Parameter=id:id_1
I put both pieces of data in a Map<String, Map<String, String>object in which the first string is the key (either a path or a parameter) and the inner map holds the actual value. I did it this way because I felt it would scale better, since I do not know beforehand how many paths or parameters are going to come with the URI (the idea is to be able to filter a given URI/concept/entity with 0 up to N filters, applying 0 or even all at the same time, and some URIs currently can have 8 filters), the path also could have several "slashes" such as /user/profile or skill/profile?date=today but as of right now it is not the case.
Example: /course can have the following filters (also called queryParameters since that's the name I saw AWS giving it at times):
skill
cost
online
duration
level
certified
language
I lack the experience to see how this can be made with scaling in mind. Currently what I am doing is something like the following example (queries are simplified for the sake of brevity). In the example, I catch whether or not a certain key appears in the map, and if present, I build the appropriate query. The biggest problem right now to apply several filters at once is that they can require a Join with different tables (suppose that for the list before, when ?skill appears I build a query with an inner join with the table skill, and when ?cost or level appears, I have to make a join with another table called course, for example) :
if(pathParameters.containsValue("profiles")) {
if(queryParameters == null || queryParameters.isEmpty()) {
try {
preparedstatement = con.prepareStatement("SELECT * from profiles");
} catch (SQLException e) {
e.printStackTrace();
}
}
else if(queryParameters.containsKey("zone")) {
try {
preparedstatement = con.prepareStatement("SELECT * from profiles where id = ? GROUP BY id;");
preparedstatement.setString(1, queryParameters.get("zone"));
} catch (SQLException e) {
e.printStackTrace();
}
}
else if(queryParameters.containsKey("skill")) {
try {
preparedstatement = con.prepareStatement("SELECT * from skills where id = ?");
preparedstatement.setString(1, queryParameters.get("skill"));
} catch (SQLException e) {
e.printStackTrace();
}
}
else if(queryParameters.containsKey("experiencia")) {
try {
[....]
}
}
}
So summing it up, I have a number of branches of logic that I cannot quite know how to simplify since each branch can have a different query associated, that needs to join a certain table. To avoid having 7! number of possibilities with IF cases, I would need to build the query more dynamically (it's the only idea I have come up with so far). For that, I would need to join two different queries with different logic, and I do not know if that is possible.
I have not yet implemented this options, but so far this looks close to what I am looking for, so I post it as an answer in case someone else may use them in the future, but so far it is a partial answer:
DbExtensions although it's for .Net and not java unfortunately.
http://www.mybatis.org/mybatis-3/statement-builders.html
Particularly code like this is what I am aiming for:
void DynamicSql(int? categoryId, int? supplierId) {
var query = SQL
.SELECT("ID, Name")
.FROM("Products")
.WHERE()
._If(categoryId.HasValue, "CategoryID = {0}", categoryId)
._If(supplierId.HasValue, "SupplierID = {0}", supplierId)
.ORDER_BY("Name DESC");
Console.WriteLine(query);
}
I have saved values retrieved from a database in java to an arraylist.
I have used a class to save the data to the array list as shown below.
ArrayList<NewSms> details = new ArrayList<NewSms>();
try{
Statement query = conn.createStatement();
ResultSet result = query.executeQuery("Select `senderAddress,message,linkid from sdp_smsincoming where status=0 AND smsServiceActivationNumber =1234 ");`
while(result.next()){
String address = result.getString("senderAddress");
String message = result.getString("message");
String linkid = result.getString("linkid");
NewSms smsdetails = new NewSms();
smsdetails.set_address(address);
smsdetails.set_message(message);
smsdetails.set_linkid(linkid);
details.add(smsdetails);;
}
}
However i now want to retrieve the values individually per row,from another class in the program.How can i do this?By individually i mean getting the address,message and linkid per row in the arraylist.
However i now want to retrieve the values individually per row,from another class in the program.How can i do this?
You just access each NewSms in the list. To access one by index, you could use:
NewSms sms = details.get(2); // Or whatever
// Now access the properties of sms
Or to access each of them in turn, use an enhanced for loop:
for (NewSms sms : details) {
// Now access the properties of sms
}
Note that to comply with Java naming conventions, your NewSms class should have methods such as getAddress, setAddress - not set_address.
Also note that you need to close your result set / statement / connection - if you're using Java 7, you can use a try-with-resources statement; otherwise you should use finally blocks.
EDIT: If your problem is actually just returning the list, that's easy:
public List<NewSms> loadSmsDetails() {
// Code as before...
return details;
}
Then just call it from your other class:
// Where repository is a reference to an instance of the class containing the above method
List<NewSms> allDetails = repository.loadSmsDetails();
for(NewSms smsdetails:details){
String address = smsdetails.get_address();
String message = smsdetails.get_message();
String linkId = smsdetails.get_linkid();
}
However i now want to retrieve the values individually per row,from
another class in the program
You need to pass the arraylist to the another class and iterate over it there to get the individual elements. The idea is to use a common araylist - to store the values from the resultset and in another class to iterate through them.
I have the following code in java:
try {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
session=sessionFactory.openSession();
Query userQuery=session.createQuery("select u.userId, u.username,p.profileContent from User as u inner join u.profiles as p");//, p.profileContent
List userList=userQuery.list();
for(int i=0;i<userList.size();i++){
System.out.println(userList.get(i));
}
}
catch(Exception e){
System.out.println(e.getMessage());
}
finally{
session.flush();
session.close();
}
I am trying to display the result of the query but only the object is displayed. Can you suggest me the way to display the contents of the objects. Currently i am getting result like:
[Ljava.lang.Object;#64bef361
for (Object o : userList) {
Object[] row = (Object[]) o;
System.out.println(Arrays.toString(row));
}
But you should probably use a debugger instead of cluttering your code with such loops.
whenever you try to print any object reference, it's toString() method is called. Now, suppose your userList is of type User. You have not overridden toString() method in your User class. So, what's happening currently is toString() method of object class is called.The Object class has implemented this method in such a way that it prints it's fully qualified package name and it's hashcode.
So, simply override this toString() method in your User class and it will start printing entire data as you have configured in this method. You can manually override this method, or if you have an IDE line netbeans or eclipse, just right click anywhere in the java file and select generate ToString method.
In Java, good programming practice is to override Object.toString() So that you avoid this problem. If you want more meaningful output then what you are getting, then adhere to the standards that are encouraged by the API.refer to the documentation when in doubt
I figured out the problem. I did not know the result of the query joining more than one tables will store the result as array of Objects class.
Query userQuery=session.createQuery("select u.userId, u.username,p.profileContent from User as u inner join u.profiles as p");//, p.profileContent
Iterator ite = userQuery.list().iterator();
while ( ite.hasNext() ) {
Object[] pair = (Object[]) ite.next();
Integer user = (Integer) pair[0];
String userName=(String) pair[1];
String profileContent=(String) pair[2];
System.out.println(user+" "+userName+" "+profileContent);
}