I have two functions: one returns a list of fields, the other returns a select query (which selects the corresponding values of the fields).
private List<Field<?>> fields() {
....
}
private Select<?> select() {
...
}
Note that the degree is determined at runtime, it depends on the user input. Hence List<Field<?>> and Select<?>.
It is possible to insert into a table:
context.insertInto(table, fields()).select(select()))
It is not possible to update a table:
context.update(table).set(DSL.row(fields()), select())
Could this functionality be added to jOOQ 3.7?
Which workaround can we use for now?
Nice catch, there's a missing method on the UpdateSetFirstStep DSL API, which accepts RowN as a first argument, the type returned from DSL.row(Collection). This should be fixed for jOOQ 3.7:
https://github.com/jOOQ/jOOQ/issues/4475
As a workaround, and if you can live with the guilt of the hack, you could cast to raw types:
context.update(table).set((Row1) DSL.row(fields()), (Select) select())
You can cast DSL.row(fields()) to Row1, because the internal implementation type returned by DSL.row(fields()) implements all Row[N] types.
Related
I have a situation where I need to return only few fields of a POJO.
Here is a SOF Question: retrieve-single-field-rather-than-whole-pojo-in-hibernate question regarding the same, but few things still seems to be obscure.
1) The answer suggests to use -
String employeeName = session.createQuery("select empMaster.name from EmployeeMaster empMaster where empMaster.id = :id").setInteger("id",10).uniqueResult();
So, here is my concern - Every pojo field is normally private, so "empMaster.name" will simply not work. And am not sure if empMaster.getName() is the solution for this. Will calling the getter methods work?
2) If i am querying multiple fields, (which is my case) (assuming getter methods work) the query will be some thing like -
List<String> employeeDetails = session.createQuery("select empMaster.getName(), empMaster.getDesignation() from EmployeeMaster empMaster where empMaster.id = :id").setInteger("id",10).uniqueResult();
Note the return type has changed from String to List<String>.
2(a) Hope this is right?
2(b) what if i am interested in age/salary of employee which will be of int type. I think the return type will be List<String> or List<Object>. Well any how in the application i can recast the String or Object to the proper type int or float etc. So this should not be a problem.
3) Now what if I am querying multiple employee details (no where clause), so the query will be something like - (not sure if the part of query after from is correct)
List<List<<String>> employeesDetails = session.createQuery("select empMaster.getName(), empMaster.getDesignation() from EmployeeMaster;
Anyway, point here is to emphasise the change in the return type to : List<List<<String>> employeesDetails. Does it work this way ???.
(The question quoted above also has answers pointing to use Projections. I have questions about it but will post them on another question, don't want to mixup.)
I will list the points in the order you mentioned them:
The query has nothing to do with the POJO's field visibility. You are doing a simple query to the database, as if you were doing a query using SQL, and columns in a table have nothing to do with the fact that their mapped POJOs' fields in an application are public or private. The difference is only the language that you're using: now you're using the Hibernate Query Language (HQL), which allows you to express your query with respect to the POJOs' definitions instead of the database's tables' definitions. In fact, doing
session.createQuery("select empMaster.getName() from EmployeeMaster...");
will throw a syntax error: there can be no parenthesis in an object's field name.
By the way, you have to parse your query result to a String, otherwise there would be a compiler semantics error.
String name = (String) session.createQuery("select empMaster.name from EmployeeMaster...").setYourParameters().uniqueResult();
When you do a query whose SELECT clause contains more than one field, and you call uniqueResult(), you're obtaining an array of Objects (Object[]). You iterate through each element in the array and cast it to the corresponding type.
First of all, you probably forgot to add a .list() method call at the end of your query.
session.createQuery("select empMaster.name, empMaster.designation from EmployeeMaster").list();
Otherwise, the query will not be executed, and you would just have a QueryImpl object waiting to be triggered.
Now, when you're expecting multiple results in your query and selecting several fields, you're getting back a List<Object[]>. The elements of the list will be the array of fields for a specific record, and the array per se will be the fields.
With reference to Inserting a row only if it does not already exist
IF NOT EXISTS returns true (if there is no row with this primary key), standard output displays a table like the following:
In my application code with datastax driver how do i capture the returned value ?
I use com.datastax.driver.mapping.Mapper.save(T) whose return type is only void
Alternatively I wish to explore Accessors implementation of datastax but not sure how to capture the return value of conditional insert.
I think you can only achieve this by using the Accessor interface.
There you can specify that your query should return a ResultSet where you can access wasApplied() which will tell you if the change has been applied or not.
I read JOOQ API documentation about following APIs, but still couldn't understand what is fieldIndex about.
fetchAny(int fieldIndex, java.lang.Class<? extends T> type)
For example, in the following code I already knows which column to select, why do we need filedIndex of 0? What does 0 mean?
String name = getDslContext().select(TESTB.STU_NAME)
.from(TESTB)
.where(TESTB.ID.eq(studentId))
.fetchAny(0, String.class);
jOOQ mostly operates on Record types. For instance, when you create the following query:
.select(TESTB.STU_NAME)
.from(TESTB)
.where(TESTB.ID.eq(studentId));
You're really operating on a ResultQuery<Record1<String>>. By calling fetchAny(0, String.class) on that type, you're telling jOOQ that you want to fetch any record, and from that record, you want to get only the value at index 0, converted to String.
This may feel like repeating the same information twice (using TESTB.STU_NAME, and fetching the column at index 0). This is because fetchign a single value is quite a special case in the jOOQ API. Unfortunately, the ResultQuery API doesn't really "know" that you're selecting only one column even if that type information is present via generics.
One alternative would be to use DSLContext.fetchValue(ResultQuery):
String name = getDslContext().fetchValue(
DSL.select(TESTB.STU_NAME)
.from(TESTB)
.where(TESTB.ID.eq(studentId))
);
I'm pretty new to the whole SQL and Java thing, but here I'm actually really confused.
I have a method which is called by invoking a few array parameters, as following
Method(String[], int, int[], int[])
I'm doing a ResultSet to check to see if there are any rows available where there is an ID match for the searched item.
ResultSet group = statement.executeQuery("SELECT * FROM `circulation` WHERE `ItemID` = "+itemID);
However, I'm completely stumped here on how to construct the method.
The String[], and int[] parameters are what is stored in the database, while the standard int parameter is the itemID. I have no idea how to go about doing this to call the Method correctly.
Darn, I thought I was doing good, too.
Arguments are normally used to provide information to the method being called. To get information from the method being called, you normally use a return value.
Your method seems to search rows in a database table named circulation for a given item ID. The item ID should thus be an argument. The found rows should be a returned value. The signature of the method should thus be:
Circulation[] findByItemId(int itemId);
Or better, using collections instead of arrays:
List<Circulation> findByItemId(int itemId);
What is Circulation? It's a class that represents what a row of the circulation table contains. So if the table contains an ID, a name and an item ID, this class would look like
public class Circulation {
private int id;
private String name;
private int itemId;
// constructor, getters, and other useful methods omitted for brevity
}
Your findByItemId() method will thus create an empty list of Circulation, then iterate over the rows of the result set, construct a Circulation instance for each row, and add the instance to the list. And then it will return that list.
Finally, you're using concatenation to build a SQL query taking parameters. This is dangerous. You should use a prepared statement instead. Read the tutorial about them.
Take a look at Apache commons-dbutils. It is a simple wrapper around JDBC and lets you convert your resultsets into any standard datastructures
You can use function
rs.getArray()
with columnName or ColumnLabel.
But this function return objects array and you can cast it to Integer and String.
The javadocs indicate that android.database.Cursor has a getType(int) method. However, when I try to call this method, Eclipse gives me an error saying no method exists. What gives?
What version of Android are you targeting? The getType() method applies only to v3.0 and later.
EDIT: Assuming you're targeting pre v3.0 versions of Android then a possible 'hack' to discover the type of each column within a table would be to query the sqlite_master table to find the CREATE data.
SELECT sql FROM sqlite_master
It's pretty nasty but if you really need to find the type then you could extend SQLiteCursor and add your own getType(int columnIndex) method.
You could perform a one-off query to the sqlite_master table when the cursor first accesses a table then parse the CREATE statement from the sql column and store the 'types' in an int[].
In the getType(int columnIndex) you would simply return the value of your int[] based on columnindex.
As I said, bit of a hack but it would work.
As you can store any type of data in (nearly) every SQLite field. Looking up the data type in sqlite_master and by using the pragma command is not a safe method. You can get the type of the fields using a query like this:
select Field1, typeof(Field1), Field2, typeof(Field2) from MyTable
This statement returns both the value of the fields and their types which might / might not change from record to record.