Multipoint from database using Geotools - java

I just want to know how to create an instance of a Multipoint from a PostGIS database.
I do the query, then get a ResultSet named area. The column with MultiPolygon attributes is named geom, so I do the following:
MultiPolygon m = (MultiPolygon)area.getObject("geom");
Forced cast doesn't work though!

You shouldn't be referencing the ResultSet directly but should work through the datastore interface which takes care of the conversion for you. See the Query Tutorial for an example of searching a dataset and retrieving geometries.
You'll need something like:
SimpleFeatureSource source = dataStore.getFeatureSource(typeName);
FeatureType schema = source.getSchema();
String name = schema.getGeometryDescriptor().getLocalName();
Filter filter = CQL.toFilter(text.getText());
Query query = new Query(typeName, filter, new String[] { name });
SimpleFeatureCollection features = source.getFeatures(query);

Related

passing parameter in sql server script file in java

I have sql files in my pc:
Example: C:\Users\User\Desktop\Queries\test.sql
Query in test.sql example :
Select * from table where colname like '%me%';
I am running this in a java program like this:
FileReader SomeName = new FileReader("C:\Users\User\Desktop\Queries\test.sql");
ResultSet rsjs = null;
rsjs = jsscript.runScript(myconn, SomeName);
This is working fine, but now I need a way to pass parameter in this sql file so that the query will be like:
Select * from table where colname like #parameter;
Is it possible?
PS: I cannot use query directly in java program. I know how to pass the parameter in query but this question is related to pass parameter in sql file. store procedure is also out of option.
You should look into StrSubstitutor https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/text/StrSubstitutor.html.
The sql string can have variables as:
String query = "Select * from table where colname like ${parameter};"
Then create a map like:
Map<String, String> values = new HashMap<>();
values.put("parameter", "%me%");
Now you can replace the variables using:
StrSubstitutor sub = new StrSubstitutor(values);
return sub.replace(query);
Edit 1:
If the query is coming from a file, you can read the file and store it in a string. Look into Files.readAllLines(path, charset)

Retrieving Data from multiple tables from Database

I have some tables in a database. They have some particular pattern. For example, consider I have table employee, then some other table with same pattern like:
table 1:employee
table 2:employee_X
table 3:employee_Y
I want to check if these tables contain data or not and if they do then I have to call some method for each table. I am using following code to retrieve.
DatabaseMetaData meta = con.getMetaData();
ResultSet res = meta.getTables(null, null, "My_Table_Name", new String[] {"TABLE"});
while (res.next()) {
if(rs.getStrin(3).equals(employee)){
//my code to write data of this table to a file
}
if(rs.getString(3).equals(employee_X)){
//my code to write data to the same file
}
if(rs.getString(3).equals(employee_Y)){
//code to write data to the same file from this table
}
}
The code is working fine, but how I can retrieve data from all these tables at once instead of using three checks. If any of these table contains data I want to write it to my file. How I can perform this operation in less lines of code and efficiently?
It would be great if anyone can suggest way to check each of these table either contain data or not in a single statement and then I can call my code to write data to file.
You can use UNION statement in your complex query. Please, check example:
SELECT id, name FROM employee WHERE id = ?
UNION
SELECT id, name FROM employee_x WHERE id = ?
UNION
...
Also you can use UNION ALL statement instead of UNION. The main difference that UNION returns unique result set without duplicates, UNION ALL allows duplicates. Please, check this link https://www.w3schools.com/sql/sql_union.asp for detailed explanation about union statement.
If you need create UNION query with custom filtered tables, please check example:
Set<String> requiredTables = new HashSet<>();
// fill set with required tables for result query
requiredTables.add("employee");
ResultSet res = meta.getTables(null, null, "My_Table_Name",
new String[] {"TABLE"});
List<String> existentTables = new LinkedList<>();
while(res.next()) {
if (requiredTables.contains(res.getString(3)) {
existentTables.add(res.getString(3));
}
}
String query = existentTables.stream().map(table -> String.format("SELECT * FROM %s", table)).collect(Collectors.joinning(" UNION "));

Ebean query using setDistinct() does not work

I'm using an ebean query in the play! framework to find a list of records based on a distinct column. It seems like a pretty simple query but the problem is the ebean method setDistinct(true) isn't actually setting the query to distinct.
My query is:
List<Song> allSongs = Song.find.select("artistName").setDistinct(true).findList();
In my results I get duplicate artist names.
From what I've seen I believe this is the correct syntax but I could be wrong. I'd appreciate any help. Thank you.
I just faced the same issue out of the blue and can not figure it out. As hfs said its been fixed in a later version but if you are stuck for a while you can use
findSet()
So in your example use
List<Song> allSongs = Song.find.select("artistName").setDistinct(true).findSet();
According to issue #158: Add support for using setDistinct (by excluding id property from generated sql) on the Ebean bug tracker, the problem is that an ID column is added to the beginning of the select query implicitly. That makes the distinct keyword act on the ID column, which will always be distinct.
This is supposed to be fixed in Ebean 4.1.2.
As an alternative you can use a native SQL query (SqlQuery).
The mechanism is described here:
https://ebean-orm.github.io/apidocs/com/avaje/ebean/SqlQuery.html
This is from the documentation:
public interface SqlQuery
extends Serializable
Query object for performing native SQL queries that return SqlRow's.
Firstly note that you can use your own sql queries with entity beans by using the SqlSelect annotation. This should be your first approach when wanting to use your own SQL queries.
If ORM Mapping is too tight and constraining for your problem then SqlQuery could be a good approach.
The returned SqlRow objects are similar to a LinkedHashMap with some type conversion support added.
// its typically a good idea to use a named query
// and put the sql in the orm.xml instead of in your code
String sql = "select id, name from customer where name like :name and status_code = :status";
SqlQuery sqlQuery = Ebean.createSqlQuery(sql);
sqlQuery.setParameter("name", "Acme%");
sqlQuery.setParameter("status", "ACTIVE");
// execute the query returning a List of MapBean objects
List<SqlRow> list = sqlQuery.findList();
i have a solution for it:-
RawSql rawSql = RawSqlBuilder
.parse("SELECT distinct CASE WHEN PARENT_EQUIPMENT_NUMBER IS NULL THEN EQUIPMENT_NUMBER ELSE PARENT_EQUIPMENT_NUMBER END AS PARENT_EQUIPMENT_NUMBER " +
"FROM TOOLS_DETAILS").create();
Query<ToolsDetail> query = Ebean.find(ToolsDetail.class);
ExpressionList<ToolsDetail> expressionList = query.setRawSql(rawSql).where();//ToolsDetail.find.where();
if (StringUtils.isNotBlank(sortBy)) {
if (StringUtils.isNotBlank(sortMode) && sortMode.equals("descending")) {
expressionList.setOrderBy("LPAD("+sortBy+", 20) "+"desc");
//expressionList.orderBy().asc(sortBy);
}else if (StringUtils.isNotBlank(sortMode) && sortMode.equals("ascending")) {
expressionList.setOrderBy("LPAD("+sortBy+", 20) "+"asc");
// expressionList.orderBy().asc(sortBy);
} else {
expressionList.setOrderBy("LPAD("+sortBy+", 20) "+"desc");
}
}
if (StringUtils.isNotBlank(fullTextSearch)) {
fullTextSearch = fullTextSearch.replaceAll("\\*","%");
expressionList.disjunction()
.ilike("customerSerialNumber", fullTextSearch)
.ilike("organizationalReference", fullTextSearch)
.ilike("costCentre", fullTextSearch)
.ilike("inventoryKey", fullTextSearch)
.ilike("toolType", fullTextSearch);
}
//add filters for date range
String fromContractStartdate = Controller.request().getQueryString("fm_contract_start_date_from");
String toContractStartdate = Controller.request().getQueryString("fm_contract_start_date_to");
String fromContractEndtdate = Controller.request().getQueryString("fm_contract_end_date_from");
String toContractEnddate = Controller.request().getQueryString("fm_contract_end_date_to");
if(StringUtils.isNotBlank(fromContractStartdate) && StringUtils.isNotBlank(toContractStartdate))
{
Date fromSqlStartDate=new Date(AppUtils.convertStringToDate(fromContractStartdate).getTime());
Date toSqlStartDate=new Date(AppUtils.convertStringToDate(toContractStartdate).getTime());
expressionList.between("fmContractStartDate",fromSqlStartDate,toSqlStartDate);
}if(StringUtils.isNotBlank(fromContractEndtdate) && StringUtils.isNotBlank(toContractEnddate))
{
Date fromSqlEndDate=new Date(AppUtils.convertStringToDate(fromContractEndtdate).getTime());
Date toSqlEndDate=new Date(AppUtils.convertStringToDate(toContractEnddate).getTime());
expressionList.between("fmContractEndDate",fromSqlEndDate,toSqlEndDate);
}
PagedList pagedList = ToolsQueryFilter.getFilter().applyFilters(expressionList).findPagedList(pageNo-1, pageSize);
ToolsListCount toolsListCount = new ToolsListCount();
toolsListCount.setList(pagedList.getList());
toolsListCount.setCount(pagedList.getTotalRowCount());
return toolsListCount;

ORMLite or Query across multiple tables

I am trying to query a table based on criteria from a join table using ORMLite.
Here is how I would express the query I am trying to write in tsql:
select * from media m inner join file f on m.fileId = f.fileId
where m.isNew = 1 OR f.isNew = 1
The result should be a list of media records where either the media record or the corresponding file record has isNew = 1.
I have read through the documentation on using OR in ORMLite, but all of the examples use a single table, not joining. Likewise I have read the documentation on joins, but none of the examples include a where clause that spans both tables. Is there any way besides a raw query to do this?
I had a look at this question: https://stackoverflow.com/a/12629645/874782 and it seems to ask the same thing, but the accepted answer produces an AND query, not an OR. Here is my code that I used to test that theory:
public List<Media> getNewMedia() {
Session session = getSession();
Account account = session.getSelectedAccount();
ContentGroup contentGroup = account.getSelectedContentGroup();
List<Media> results = null;
try {
QueryBuilder<Category, Integer> categoryQueryBuilder = getHelper().getCategoryDao().queryBuilder();
categoryQueryBuilder.where().eq("group_id", contentGroup.getId());
QueryBuilder<MediaCategory, Integer> mediaCatQb = getHelper().getMediaCategoryDao().queryBuilder();
mediaCatQb = mediaCatQb.join(categoryQueryBuilder);
QueryBuilder<FileRecord, Integer> fileQueryBuilder = getHelper().getFileDao().queryBuilder();
fileQueryBuilder.where().ge("lastUpdated", contentGroup.getLastDownload());
QueryBuilder<Media, Integer> mediaQb = getHelper().getMediaDao().queryBuilder();
mediaQb.where().eq("seen", false);
// join with the media query
results = mediaQb.join(fileQueryBuilder).join(mediaCatQb).query();
} catch (SQLException e) {
Log.e(TAG, "Sql Exception", e);
}
return results;
}
For the sake of completion, this is querying for a slightly more complex example than the one I gave above, this one expressed in tsql would be
select * from Media m join FileRecord f on m.fileRecordId = f.fileRecordId
where m.seen = false OR f.lastUpdated >= lastUpdateDate
When I run it, it is actually doing an AND query, which is what I would expect based on two joins with independent where clauses.
I think the key issue is that a where clause is inherently tied to a table, because it is performed on a QueryBuilder object which comes from a Dao that is specific to that table. How can I get around this?
I think what you are looking for is joinOr search for it in the ORMLite docs.
Like join(QueryBuilder) but this combines the WHERE statements of two
query builders with a SQL "OR".

Mapping RawSql Result to Object in Java Ebean

Let's say I have a class Article which is automatically mapped by Java Ebean as a database table.
For this table I wanted to retrieve entries via a RawSql query, because I find SQL more simple when it gets to complex queries with many joins and such. By far I have managed to give my SQL statement to the Parser. The query is correct, I already checked that.
The only problem is, that I don't know, how to map the database results to my Article class. I know, that there is a columnMapping(...) method but honestly, I am to lazy to map every single column manually...
Isn't there another way to just like myResults.mapToClass(Article.class) to retrieve something like a List<Article>?
This is the code I already have:
Finder<String, Article> find = new Finder<String, Article>(
String.class, Article.class);
String sql = "SELECT * FROM article [...]";
RawSql rawSql = RawSqlBuilder.parse(sql).create();
List<Article> returnList = find.setRawSql(rawSql).findList();
Alternatively:
Finder<String, Article> find = new Finder<String, Article>(
String.class, Article.class);
String sql = "SELECT id, title, sub_title FROM article [...]";
RawSql rawSql = RawSqlBuilder.parse(sql)
.columnMapping("id", "id")
.columnMapping("title", "title")
.columnMapping("sub_title", "subTitle")
.create();
List<Article> resultList = find.setRawSql(rawSql).findList();
A lot of happened in Ebean since the question was asked, but I think the problem is still valid. the new RawSqlBuilder.tableMapping() makes things easier as can be seen in the code below, but afaik it still needs manual mapping of all attributes (no SELECT table.* FROM table)
I have this exact problem, and worked around this by creating a helper object (#Entity/#Sql) that I map to. E.g. CustomerWithPurchaseStats.
Extract:
#Entity
#Sql
public class CustomerWithPurchaseStats {
#OneToOne
private Customer customer;
...
And in the DAO:
public List<CustomerWithPurchaseStats> getAllCustomersWithPurchaseStats() {
StringBuilder sql = new StringBuilder("SELECT cu.id, <manually add all fields you need mapped ").append(" FROM customer cu ");
RawSqlBuilder rawSqlBuilder = RawSqlBuilder.parse(sql.toString());
rawSqlBuilder.tableAliasMapping("cu", "customer").create();
return Ebean.find(CustomerWithPurchaseStats.class)
.setRawSql(rawSqlBuilder.create())
.findList();
}

Categories