JOOQ - convert fetchOne().into() to fetchValue(query) - java

In this answer, the author mentions that to avoid NPE the fetchValue(query) method can be used. The problem is that how exactly can the OP's code be converted into a query? I have similar code, pasted below, and would like to turn it into a query also.
return jooqDSLContext.select()
.from(CL_LOGIN)
.join(CL_USERS)
.on(CL_LOGIN.CL_USER_ID.eq(CL_USERS.CL_USER_ID))
.where(CL_USERS.EMAIL1.eq(email))
.fetchOne().into(CL_LOGIN);
JOOQ is very powerful and has many capabilities, but unfortunately everything I have tried to make a standalone query object with a join does not even compile.
EDIT: The answer provided did help me side-step the need to have a query object. But for those that want to know how to get a query object you can use the getQuery() method... see example below.
SelectQuery<Record1<String>> query = jooqDSLContext.select(USER_LOGIN.ACCOUNT_STATUS)
.from(USER_LOGIN)
.where(USER_LOGIN.USER_ID.eq(userId))
.getQuery();

Observe the signature of the method DSLContext.fetchValue(ResultQuery<R>), where R extends Record1<T>. This means that the expected row type of the query is Record1<T> with any arbitrary <T> type. In other words, you must project exactly one column in your SELECT clause.
You seem to want to project the entire record of type CL_LOGIN, so fetchValue() is not applicable to your use-case.
But note, there's also ResultQuery.fetchOneInto(Table), which is a convenience method wrapping that null check and the into() call. So, just write:
return jooqDSLContext.select()
.from(CL_LOGIN)
.join(CL_USERS)
.on(CL_LOGIN.CL_USER_ID.eq(CL_USERS.CL_USER_ID))
.where(CL_USERS.EMAIL1.eq(email))
.fetchOneInto(CL_LOGIN);

Related

How to create 'update' using multiple 'set' methods

Synopsis: I'm trying to create an SQL update using jOOQ
DSL.using(connection)
.update(DSL.table("dogs"))
.set(DSL.field("age"), DSL.field("age").add(1))
.set(DSL.field("rabies"), "true")
.where(DSL.field("id").eq("Kujo"))
.execute();
Issue:
The method set(Field<Object>, Object) is ambiguous for the type UpdateSetFirstStep<Record>
Question: How do I create this update using jOOQ?
You ran into this problem: Reference is ambiguous with generics
Fixing your query
It's always a good idea to attach data types with your jOOQ expressions. In your particular case, you can work around the problem by specifying things like:
DSL.field("age", SQLDataType.INTEGER)
Or, shorter, with the usual static imports:
field("age", INTEGER)
Using the code generator
However, jOOQ is best used with its code generator, see also this article here. Not only will you avoid problems like these, but you also get compile time type safety (of data types and meta data), advanced features like implicit joins and much more.
Your query would then look like this:
DSL.using(connection)
.update(DOGS)
.set(DOGS.AGE, DOGS.AGE.add(1))
.set(DOGS.RABIES, true)
.where(DOGS.ID.eq("Kujo"))
.execute();

Why doesn't createNativeQuery return a TypedQuery<T>?

When I try to do a TypedQuery of a type that is generic, I get a unchecked type conversion warning from Eclipse.
I am using a generic here because in the dataset, every year has to be separated into a different table due to time constraints on queries and edits. There are 118 years of data in the table (since 1900), and I would like to build a system that can extend itself every year using the Java Reflections API. However, this means that prior to compilation, my parent classes don't know which child class or table they will be operating on.
Here is an example of some code that will cause an unchecked warning even though I'm specifying what type everything is through a TypedQuery. The code I have will compile and run just fine on my database.
public class MyParentRepository<T extends MyParentPojo>
{
#PersistenceContext
private EntityManager em;
private Class<T> tea;
public MyParentRepository(Class<T> tea)
{
this.tea = tea;
}
public void giveWarning(int year)
{
String sql = String.format("SELECT * FROM mytable%d t", year);
TypedQuery<T> resultSet = (TypedQuery<T>) em.createNativeQuery(sql, tea);
}
}
The expected result is that since tea is guaranteed to be instantiated with the generic type , as it's the same type everywhere and once instantiated it can't be changed, so the compiler should understand that the Entity Manager is going to return a TypedQuery of type as well. However, it results in an unchecked type warning even though it's guaranteed to work.
I've seen people suggest fixing an unchecked type warning by going from a Query to TypedQuery, but that isn't helping in this case. Is there a way to avoid this warning while still doing what I am trying to do?
In response to an answer that was deleted, I would like to clarify something.
em.createQuery(String)
em.createQuery(String, Class<T>)
em.createNativeQuery(String)
em.createNativeQuery(String, Class)
Of these options, the first takes in a JPQL string and returns a
generic Query.
Option 2 takes in a JPQL string and a specific class representing a table
row, and returns a TypedQuery.
Option 3 takes in a SQL string and returns a generic Query.
Option 4 takes in a SQL string and a specific class representing a table row,
and why does it return a generic Query and not a TypedQuery?
It seems to me that if I am giving it a POJO of the appropriate type, option 4 should figure out how to serialize it like Option 2 does for me. In fact it does, but it doesn't set the type correctly like Option 2. This is not acceptable from my point of view since not every SQL query can be represented by a JPQL query, so there may be times I need to use SQL, and I would expect to have a TypedQuery returned.
I've solved the warning I had by switching to option 2, but I still would like to know the answer in case as I said, a situation arises where I cannot use Option 2 in the future.
Its because createNamedQuery returns Query not TypedQuery<T> even in "typed result" variant.
https://docs.oracle.com/javaee/7/api/javax/persistence/Query.html

underlying procedure for someMethod(SomeClass.class)

in hibernate to create criteria we use
Criteria criterea=session.createCritera(SomeClass.class)
It may be available in some other examples too but I am not able to understand the structure of these type of methods.
NOTE this is an example I am trying to put to understand use of SomeClass.class like arguments
my question here is what is purpose of SomeClass.class ? why do we need it, what is the advantages of using it as argument.
Edit its not a duplicate but have string connection to this question
What is this .class syntax?
If you attach .class to the end of a class name, you get the Class<T> object corresponding to the class.
Examples:
String.class returns an instance of Class<String>
Integer.class returns an instance of Class<Integer>
What can you do with a class object
Reflection! If you have access to a class object, you can do all kinds of cool stuff! You can call methods, get and set values of fields...
Why is this used in Hibernate?
I haven't used hibernate before, but this syntax is used in other libraries as well, especially in ORMs or JSON serializers. I'll use JSON serializers as an example as I'm more familiar with those.
In a JSON serializer, you need to give it a class object because it needs to get all the fields that you want to serialize to JSON. It uses reflection to get and set the values of those fields, then convert them to JSON. When it deserializes JSON, it finds the field that needs to be set with the name in the JSON. These operations require a Class object because without it, how can Java know which class should it find the field? Also, to create a new object with reflection, a Class is needed as well!
Hibernate provides many ways to handle the objects in relation with RDBMS tables.
One way is Session interface providing createCriteria() method which can be used to create a Criteria object.
As name says criteria, it is useful to execute queries by applying filtration rules and logical conditions of programmer wish.
For example:
Criteria obj=session.createCritera(Galaxy.class) // say SomeClass is Galaxy.class
List results = obj.list();
Here, criteria query is one which will simply return every object that corresponds to the Galaxy class.
We even can restrict the results with criteria, example add() method available for Criteria object to add restriction for a criteria query.
Following is the restriction to return the records with planet which has 7.4 billion population from Galaxy class:
Criteria cr = session.createCriteria(Galaxy.class);
cr.add(Restrictions.eq(“planet”, 75000000000));
List results = cr.list();

'distinct' MongoDB function in java program

I am pretty new to mongo db, and I have a simple question regarding a trouble I can’t solve in my Java program (3.0.2 client version). My aim is to perform a distinct on the “cars” test database, and I am trying this code:
DistinctIterable<Object> classification = collection.distinct("classification", null);
I can’t figure out what should I put in the second parameter. Could you help me please?
If you are using the Java API, I think that you can pass just the first argument, that would be the one on which do the distinct. The second parameter would be the query to filter on, but it can be omitted according to the documentation.
public List distinct(String fieldName)
Find the distinct values for a specified field across a collection and returns the results in an array.
Parameters:
fieldName - Specifies the field for which to return the distinct values.
Returns:
a List of the distinct values
You need to provide the class to map to, see http://api.mongodb.org/java/current/com/mongodb/client/MongoCollection.html

Hibernate - Extract parameter values from SQL query

I have a class that populates a Hibernate SQL query's parameters with different values depending on some input criteria. I would like to write tests for the resulting query. As of yet, I have not found a way to get the parameter values that were set on a query. I looked at the resulting Query implementation (in this case, SQLQueryImpl) and there is a method called getParameterMetadata() that seems like it might give me something, but I haven't been able to find anything.
I would like to be able to do something like:
assertEquals("some value", query.getParameterValue(parameterName));
Is there a way to do this?
EDIT:
I just looked a little more, and I found a
query.getQueryParameters(map).getNamedParameters()
which returns a Map. I have to assume that the map contains the parameters and their values. Correct me if I'm wrong.
I actually didn't consider the fact that because I'm testing, I can simply mock the query and expect specific parameters.

Categories