Ormlite query help for newbie - ormlite

Having a few problems with Ormlite and Android/Sqlite so any help appreciated. The database structure is
"CREATE TABLE [jobTasks](" +
"[JobTaskID] varchar(50) NOT NULL PRIMARY KEY DEFAULT (newid())," +
"[JobID] varchar(50) NOT NULL," +
"[EnumTaskType] Real," +
"[TaskID] varchar(50)," +
"[TaskOrder] SmallInt," +
"[TaskDescription] NVarChar (50) ," +
"[EnumTaskStatus] Real," +
"[EnumTaskQualifier] Real," +
"[IsTaskQualifierForced] Bit," +
"[CompletedBy] NVarChar (50)," +
"[CompletedOn] DateTime," +
"[CompletedOnOffset] NVarChar (6)," +
"[JobAssetID] varchar(50),[wadtDeleted] Bit NOT NULL DEFAULT ((0))," +
"[WadtModifiedBy] NVarChar (15)," +
"[WadtModifiedOn] DateTime," +
"[WadtModifiedOnDTOffset] NVarChar (6)," +
"[WadtRowID] varchar(50) DEFAULT (newid())," +
"[ParentJobTaskID] varchar(50)," +
"[Rowguid] varchar(50) NOT NULL DEFAULT (newid())," +
"SyncDeleted Bit NOT NULL DEFAULT ((0))," +
"FOREIGN KEY(JobID) REFERENCES jobJob(jobID)," +
"FOREIGN KEY(enumTaskType) REFERENCES enumTaskType(enumTaskType)," +
"FOREIGN KEY(TaskID) REFERENCES cfgWorkFlowTasks(TaskID)," +
"FOREIGN KEY(enumTaskStatus) REFERENCES enumTaskStatus(enumTaskStatus))"
The query is
QueryBuilder<JobParentTask, String> qb =
_databaseContext.JobParentTasks().queryBuilder();
qb.orderBy(JobParentTask.TASKORDER, true);
qb.where().eq(JobParentTask.JOBID, id).and()
.isNull(JobParentTask.PARENTJOBTASKID);
PreparedQuery<JobParentTask> preparedQuery = queryBuilder.prepare();
CloseableIterator<JobParentTask> iterator
=_databaseContext.JobParentTasks().iterator(jobParentTaskPreparedQuery);
while (iterator.hasNext()) {
parentTasks.add(iterator.next());
}
The following error is thrown
unrecognized token: "6B582835": , while compiling:
SELECT * FROM `jobTasks` WHERE
`JobID` = 6B582835-5A79-E011-A5E4-005056980009 AND `ParentJobTaskID` IS NULL )
ORDER BY `TaskOrder`
If I am passing the id as a string value why does it not show as such in the query?
The final error thrown is
java.sql.SQLException: Could not build prepared-query iterator for class
conx.Entities.JobParentTask
I assume this is related to the original error?
Thanks in advance

Will hang my head in shame. The JOBID was associated as a column name annotation for the wrong column.

Huh. I suspect you have an existing database table that you are trying to match a Java class against? Any chance that the JobID field in your Java class is not a string but is, by accident, an integer?
The eq(JobParentTask.JOBID, id) method should look at the field inside of JobParentTask and see that it is a String that needs to be escaped. This is core code in ORMLite that has been working for some time.
Can you post the JobParentTask definition around the JobID field?
If you still are having problems an immediate workaround is to use the "Select Args":
http://ormlite.com/docs/select-arg
Something like:
SelectArg jobIdArg = new SelectArg(id);
queryBuilder.where().eq(JobParentTask.JOBID, jobIdArg).and()...
Then the query that is constructed used a ? and injects the argument using SQL.

Related

Springboot JPA Cast numeric substring to string

I have a JPA/Springboot application backed by a Postgres database. I need to get a records that is equal to a substring passed back to the server.
For example:
Select * from dp1_attachments where TRIM(RIGHT(dp1_submit_date_dp1_number::text, 5)) ='00007'
This query works in PgAdmin, but not in the JPA #Query statement.
#Query("SELECT a.attachmentsFolder as attachmentsFolder, a.attachmentNumber as attachmentNumber, a.attachmentName as attachmentName, a.dp1SubmitDateDp1Number as dp1SubmitDateDp1Number,a.attachmentType as attachmentType, a.attachmentDate as attachmentDate, a.attachmentBy as attachmentBy "
+ "FROM DP1Attachments a WHERE TRIM(SUBSTRING(a.dp1SubmitDateDp1Number::text, 5 )) = :dp1Number")
I've also tried CASTing the parameter like this:
#Query("SELECT a.attachmentsFolder as attachmentsFolder, a.attachmentNumber as attachmentNumber, a.attachmentName as attachmentName, a.dp1SubmitDateDp1Number as dp1SubmitDateDp1Number,a.attachmentType as attachmentType, a.attachmentDate as attachmentDate, a.attachmentBy as attachmentBy "
+ "FROM DP1Attachments a WHERE TRIM(SUBSTRING(CAST(a.dp1SubmitDateDp1Number as string, 5 ))) = :dp1Number")
but the application won't even run, and returns an error that the query isn't valid.
If I make no attempt to cast it, I get an error that function pg_catalog.substring(numeric, integer) does not exist
UPDATE
I've also tried creating a native query instead but that also doesn't seem to work.
List<DP1AttachmentsProjection> results = em.createNativeQuery("Select * FROM dp1_attachments WHERE TRIM(RIGHT(CAST(dp1_submit_date_dp1_number as varchar),5)) =" + dp1Number).getResultList();
In place of varchar I have also tried string and text.
Errors come back similar to ERROR: operator does not exist: text = integer. Its like the CAST is being ignored and I'm not sure why.
I also tried the following as a native query:
em.createNativeQuery("Select * FROM dp1_attachments WHERE TRIM(RIGHT(dp1_submit_date_dp1_number::varchar),5)) =" + dp1Number).getResultList();
and get ERROR: syntax error at or near ":"
FINAL SOLUTION
Thanks to #Nenad J I altered the query to get the final working solution:
#Query(value = "SELECT a.attachments_Folder as attachmentsFolder, a.attachment_Number as attachmentNumber, a.attachment_Name as attachmentName, a.dp1_Submit_Date_Dp1_Number as dp1SubmitDateDp1Number,a.attachment_Type as attachmentType, a.attachment_Date as attachmentDate, a.attachment_By as attachmentBy FROM DP1_Attachments a WHERE TRIM(RIGHT(CAST(a.dp1_Submit_Date_Dp1_Number as varchar ), 5 )) = :dp1Number", nativeQuery = true)"
Default substring returns a string, so substring(integer data,5) returns a string. Thus no need for the cast.
#Query("SELECT * FROM DP1Attachments a WHERE TRIM(SUBSTRING(a.dp1SubmitDateDp1Number, 5)) = :dp1Number")
But I recommend in this case use native query like this:
Put this code in your attachment repository.
#Query(value="SELECT * FROM DP1Attachments AS a WHERE TRIM(SUBSTRING(a.dp1SubmitDateDp1Number, 5 )) = :dp1Number", nativeQuery=true)
Be careful with the column's name.

Hibernate: StoredProcedure with recursive depthsearch: Mapping/Output Problems

I searching for help. I have to map my Postgres 9.4 Database (DB) with Hibernate 5.2, of course it's an study task. The biggest Problem is, that I'm no brain in Hibernate, Java and coding itself XD
It's an SozialNetwork DB. To map the DB with Hibernate doing fine.
Now I should map a stored produce. This Produce should find the shortest friendship path between two persons. In Postgres the produce working fine.
That are the relevant DB-Tables:
For Person:
CREATE TABLE Person (
PID bigint NOT NULL,
firstName varchar(50) DEFAULT NULL,
lastName varchar(50) DEFAULT NULL,
(some more...)
PRIMARY KEY (PID)
);
And for the Relationship between to Persons:
CREATE TABLE Person_knows_Person (
ApID bigint NOT NULL,
BpID bigint REFERENCES Person (PID) (..)
knowsCreationDate timestamp,
PRIMARY KEY (ApID,BpID));
And that is the Stored Produce in short:
CREATE OR REPLACE FUNCTION ShortFriendshipPath(pid bigint, pid2 bigint)
RETURNS TABLE (a_pid bigint, b_pid bigint, depth integer, path2 bigint[], cycle2 boolean)
AS $$
BEGIN
RETURN QUERY
SELECT * FROM (
WITH RECURSIVE FriendshipPath(apid, bpid, depth, path, cycle) AS(
SELECT pkp.apid, pkp.bpid,1,
ARRAY[pkp.apid], false
FROM person_knows_person pkp
WHERE apid=$1 --OR bpid=$1
UNION ALL
SELECT pkp.apid, pkp.bpid, fp.depth+1, path || pkp.apid,
pkp.apid = ANY(path)
FROM person_knows_person pkp, FriendshipPath fp
WHERE pkp.apid = fp.bpid AND NOT cycle)
SELECT *
FROM FriendshipPath WHERE bpid=$2) AS OKOK
UNION
SELECT * FROM (
WITH RECURSIVE FriendshipPath(apid, bpid, depth, path, cycle) AS(
SELECT pkp.apid, pkp.bpid,1,
ARRAY[pkp.apid], false
FROM person_knows_person pkp
WHERE apid=$2 --OR bpid=$1
UNION ALL
SELECT pkp.apid, pkp.bpid, fp.depth+1, path || pkp.apid,
pkp.apid = ANY(path)
FROM person_knows_person pkp, FriendshipPath fp
WHERE pkp.apid = fp.bpid AND NOT cycle)
SELECT *
FROM FriendshipPath WHERE bpid=$1) AS YOLO
ORDER BY depth ASC LIMIT 1;
END;
$$ LANGUAGE 'plpgsql' ;
(Sorry for so much code, but it's for both directions, and before I post some copy+reduce misttakes^^)
The Call in Postgre for example:
SELECT * FROM ShortFriendshipPath(10995116277764, 94);
gives me this Output:
enter image description here
I use the internet for help and find 3 solutions for calling:
direct SQL call
call with NamedQuery and
map via XML
(fav found here)
I faild with all of them XD
I favorite the 1. solution with this call in session:
Session session = HibernateUtility.getSessionfactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
System.out.println("Please insert a second PID:");
Scanner scanner = new Scanner(System.in);
long pid2 = Long.parseLong(scanner.nextLine());
// **Insert of second ID*/
Query query2 = session.createQuery("FROM " + Person.class.getName() + " WHERE pid = :pid ");
query2.setParameter("pid", pid2);
List<Person> listB = ((org.hibernate.Query) query2).list();
int cnt1 = 0;
while (cnt1 < listB.size()) {
Person pers1 = listB.get(cnt1++);
pid2 = pers1.getPid();
}
// Query call directly:
Query querySP = session.createSQLQuery("SELECT a_pid,path2 FROM ShortFriendshipPath(" + pid + "," + pid2 + ")");
List <Object[]> list = ((org.hibernate.Query) querySP).list();
for (int i=0; i<list.size();i++){
Personknowsperson friendship = (Personknowsperson)result.get(i);
}
} catch (Exception e) { (bla..)}
} finally { (bla....) }
Than I get following Error:
javax.persistence.PersistenceException:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 2003
(..blabla...)
I understand why. Because my output is not of type Personknowsperson. I found an answer: that I have to say Hibernate what is the correct formate. And should use 'UserType'. So I try to find some explanations for how I create my UserType. But I found nothing, that I understand. Second Problem: I'm not sure what I should use for the bigint[] (path2). You see I'm expert -.-
Than I got the idea to try the 3.solution. But the first problem I had was where should I write the xml stuff. Because my Output is no table. So I try in the .cfg.xml but than Hibernate say that
Caused by: java.lang.IllegalArgumentException: org.hibernate.internal.util.config.ConfigurationException: Unable to perform unmarshalling at line number -1 and column -1 in RESOURCE hibernate.cfg.xml. Message: cvc-complex-type.2.4.a: Ungültiger Content wurde beginnend mit Element 'sql-query' gefunden. '{some links}' wird erwartet.
translation:
invalid content found starts with 'sql-query'
Now I'm a nervous wreck. And ask you.
Could someone explain what I have to do and what I did wrong (for dummies please). If more code need (java classes or something else) please tell me. Critic for coding also welcome, cause I want improve =)
Ok, I'm not an expert in postgressql, not hibernate, nor java. (I'm working with C#, SQL Server, NHibernate so ...) I still try to give you some hints.
You probably can set the types of the columns using addXyz methods:
Query querySP = session
.createSQLQuery("SELECT * FROM ShortFriendshipPath(...)")
.addScalar("a_pid", LongType.INSTANCE)
...
// add user type?
You need to create a user type for the array. I don't know how and if you can add it to the query. See this answer here.
You can also add the whole entity:
Query querySP = session
.createSQLQuery("SELECT * FROM ShortFriendshipPath(...)")
.addEntity(Personknowsperson.class)
...;
I hope it takes the mapping definition of the corresponding mapping file, where you can specify the user type.
Usually it's much easier to get a flat list of values, I mean a separate row for each different value in the array. Like this:
Instead of
1 | 2 | (3, 4, 5) | false
You would get:
1 | 2 | 3 | false
1 | 2 | 4 | false
1 | 2 | 5 | false
Which seems denormalized, but is actually the way how you build relational data.
In general: use parameters when passing stuff like ids to queries.
Query querySP = session
.createSQLQuery("SELECT * FROM ShortFriendshipPath(:pid1, :pid2)")
.setParameter("pid1", pid1)
.setParameter("pid2", pid2)
...

npgsql : Selecting a null data throws exception with error "Column is Null"

I am running npgsql v3.7 with .NetCore on Ubuntu.
When I execute a select query and a cell in any row in the results is null, an exception is thrown with the error message "Column is null".
I am having to work around this by putting every column in the select clause inside a case statement which tests for NULL
"CASE WHEN " + fieldName + " IS NULL THEN '' ELSE " + fieldName + " END "
This seems a bit extreme and should not be necessary. Has anyone else come across this.
Thanks.
You are probably trying to read the column like this:
using (var reader = cmd.ExecuteReader()) {
reader.Next();
var o = reader.GetString(0); // Or any other of the Get methods on reader
...
}
This code will fail if the column contains a null, and is the expected behavior. In ADO.NET, you need to check for a null value with reader.IsDBNull(0) before actually getting the value. That's just how the database API works.
I don't know why NULL values are giving you errors, but you can do away with the ugly CASE statement in favor of using COALESCE:
"COALESCE(" + fieldName + ", '')"
Ideally you should make a configuration change such that NULL values do not cause this problem.

Sql column alias not working in Ebeans rawsql

I am facing strange issue with raw SQLs, and I need some help to figure out the best way to fix it. I could, of course, add the columnMappings, but I want to make sure it's not because I am doing something wrong.
Play Framework APP
Ebeans ORM
Postgresql 9.,4
Executing the following RawSQL against a Postgresql database fails if I don't define columnMappings, although I have an alias defined:
String sql
= " Select date_trunc('day', end_time) as theDate, "
+ " count(*) as value "
+ " From ebay_item "
+ " group by date_trunc('day', end_time) ";
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.create();
Error:
016-03-25 12:05:15,303 ERROR m.c.a.e.s.p.SimpleDBPromiseService - Error executing named query
javax.persistence.PersistenceException: Property [dateTrunc('day'] not found on models.com.abiesolano.ebay.sqlpojos.RangedDateCounter
If I switch to an H2 database:
String sql
= " SELECT trunc(end_time) as theDate, "
+ " count(*) as value "
+ " From ebay_item "
+ " Group by trunc(end_time)";
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.create();
it works no problems.
Any suggestion would be really appreciated.
I don't think mysql likes to group or order by functions, you should use your alias "theDate" instead.
Note that if you're mapping to a bean object, the alias must be a #Transient property of your bean to be mapped by Ebean (otherwise, you'll get an unknown property error).

IF EXISTS not recognized in Derby

DROP TABLE IF EXISTS Pose ;
results in the error
Error code -1, SQL state 42X01: Syntax error: Encountered "EXISTS" at line 1, column 15.
I'm running this from inside NetBeans 7.3 using the default Derby sample db.
Derby does not currently support IF EXISTS
Are you trying to create a table? If yes, this is what you should do:
public void createTables() throws SQLException {
Statement statement = getConnection().createStatement();
System.out.println("Checking database for table");
DatabaseMetaData databaseMetadata = getConnection().getMetaData();
ResultSet resultSet = databaseMetadata.getTables(null, null, "PATIENT", null);
if (resultSet.next()) {
System.out.println("TABLE ALREADY EXISTS");
} else {
//language=MySQL
statement.execute("CREATE TABLE Patient (" +
"CardNumber CHAR(10) NOT NULL PRIMARY KEY, " +
" FirstName CHAR(50)," +
" MiddleName CHAR(50)," +
" LastName CHAR(50) )");
}
}
Remember to use all caps for the table name you pass into databaseMetadata.getTables(...)
The MySQL 6.0 syntax for declaring a table is this:
CREATE TABLE [IF NOT EXISTS] tableName ...
and the MySQL syntax for removing a table is this:
DROP TABLE [IF EXISTS] tableName ...
These clauses are MySQL extensions which are not part of the ANSI/ISO SQL Standard. This functionality may be peculiar to MySQL: I can't find anything similar documented for Derby, Postgres, Oracle, or DB2.
The best alternative I can find is to query the system tables to see if the table exists.
select count(*) from sys.systables where tablename = 'YOUR_TABLE_NAME'"
I had a similar issue dropping stored procedures. They can be queried using this statement.
select count(*) from sys.sysaliases where alias = 'YOUR_STORED_PROCEDURE_NAME'
If someone is looking to drop and create a table in an sql file that is Run with Spring test framework, Check https://stackoverflow.com/a/47459214/3584693 for an answer that ensures that no exception is thrown when drop table is invoked when said table doesn't exist.