I am new to JPA 2.0/EclipseLink/Glassfish/JEE6, and have kind of a basic question.
I have a DAO in which most of the entities are mapped directly to columns using JPA annotations, so I use the EntityManager, and it works great with no issues.
However there are some tables in which I am constructing the SQL statements myself b/c they use oracle-specific functions (spatial), and I want very fine-grained control of the SQL. So I am building it with string concatenation. I would like to be able to enroll my SQL executions in the current transaction, if there is one already underway.
So naturally I don't want to go directly to the DriverManager and create my own connection, I was looking for some kind of EntityManager.executeArbitrarySQL(String) function that would find the current connection and make my SQL part of the current transaction. Am I off my rocker?
One can use the EntityManager.createNativeQuery() methods to execute native SQL queries within the context of the same EntityManager that you are using. There are two three different types of these methods, and they differ in the arguments provided.
The first, createNativeQuery(String sqlString, Class resultClass) expects you to provide the Class object representing the type of the values that will be returned by the query. This is to be used in case you are returning a set of values that can be mapped to the class of another entity definiton in your persistence unit.
The second createNativeQuery(String sqlString, String resultSetMapping) expects you to provide the name of the result set mapping. The result set mapping ought to be defined using the #SqlResultSetMapping annotation.
The last createNativeQuery(String sqlString) is apparently meant to be used in scenarios where no result set will be returned, i.e. in execution of INSERT, UPDATE and DELETE statements.
You can also define native queries using the #NamedNativeQuery annotation or the named-native-query element in your persistence.xml file, but these are better suited for scenarios where you know the structure of the query during development. You can however, create multiple such named native queries to represent all varieties of the SQL statement you intend to execute, and then execute different ones at runtime based on the user inputs. Annotated native queries are executed using the EntityManager.createNamedQuery() methods. One will need to use positional parameters (defined using the ? placeholder) to supply values to the native queries at runtime.
Related
I write many Maximo Where Clauses (which use Oracle SQL), and save them as public queries.
I encourage others to edit/customize the work I share with them.
But when my query uses the same string throughout it many times, it's tedious to make sure all instances are replaced. It's not like there's a built-in find-replace tool or anything.
Is there a way to define a custom string variable at the beginning, and reuse that variable many times thoughout the where clause?
No, you can't do that. But what you could do is make a relationship from your parent object to a system property / maxpropvalue child object where propname = 'company.app.varname. Then, you can use the System Properties app to change the value of the variable for all references. And you can make a reference to it in your query using standard :relationshiptomaxpropvalue.propvalue syntax.
HTH.
I want to know if it's possible to pass in a list as a parameter in native queries.
When search up online, an article in Baeldung has exactly what I want to do:
Collection-Valued Positional Parameters usage
I did the exact same thing, except that in the article, they used "createQuery" and I used "createNativeQuery". Not sure if this is the reason why mine is not working.
CreateQuery means JPQL was passed in which is parsed and modified into SQL, which allows it to break the collection parameter into its components to pass each into the SQL statement. CreateNativeQuery uses your SQL which isn't modified, and JDBC doesn't understand collections so requires parameters broken up into individual arguments in the SQL. You have to do it yourself and dynamically build the SQL based on the number of parameters in the collection.
There are other questions with solutions that touch on other options, such as using SQL within criteria or JPQL queries that can let you get the best of both.
One way of conducting an SQL query is the defined NamedQuery in JPA:
Query query = entityManager.createNamedQuery("Users.findByName");
An alternative to this is running it without defining a NamedQuery:
Query query = entityManager.createQuery("SELECT SELECT u FROM Users u");
From what i see, NamedQuery is favorable for it is defined at one-place-for-all in the entity class and is available to a pojo that has a use for it without getting into SQL.
Are there any differences between the two?
The only difference is that one is a String that only can be used in the class where is declared, the one of your second example
Query query = entityManager.createQuery(" SELECT u FROM Users u");
The NamedQueries can be used in different DAO without need to define them again, just call and PersistenceProvider will find them using #NamedQueries - #NamedQuery, or xml files when you define them.
Basically a named queries are a powerful tool for organizing query
definition and improving application performance.
Also a good important stuff is that some provider processed the JPQL inside the namedqueries at the startup time, this gives a hit on the performance, in the second case that you set in yout question, persistence provider is not aware of the query existence and does not have the chance to process it on startup and need to run the process when is required.
I have a table, CityComplete, with columns "USPSCITY", "STATE" and "ZIPCODE"
I have an existing SQLQuery that distinctly selects USPSCITY and STATE based on a fuzzy search. However, when I call list() I get an exception:
19. ResultSet.getString(ZIPCODE)
java.sql.SQLException: Column 'ZIPCODE' not found.
The SQLQuery's entity is set to the CityComplete object.
Is there any way to have Hibernate not try and get ZIPCODE, or have it be part of the result set in some way?
What's the best way to resolve this, other than using Criteria, setting a virtual column with null data, or just getting a full result set and handling distinction on the code side?
When you perform a regular Hibernate query (HQL or Criteria), Hibernate will try to map the resultset based on the properties of the entities which you specified in the mapping. If you are not bringing the "promised" data from the database, you'll need to handle the mapping by yourself, using a ResultTransformer. In this case, you'd still use your CityComplete, but they will be without a ZIPCODE. Unfortunately, there's not much documentation about how to use a ResultTransformer, but you can take a look at the Hibernate's JavaDoc and see if there's one that you could use. If not, you'd need to implement your own:
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/transform/ResultTransformer.html
I essentially have a database layer that is totally isolated from any business logic. This means that whenever I get ready to commit some business data to a database, I have to pass all of the business properties into the data method's parameter. For example:
Public Function Commit(foo as object) as Boolean
This works fine, but when I get into commits and updates that take dozens of parameters, it can be a lot of typing. Not to mention that two of my methods--update and create--take the same parameters since they essentially do the same thing. What I'm wondering is, what would be an optimal solution for passing these parameters so that I don't have to change the parameters in both methods every time something changes as well as reduce my typing :) I've thought of a few possible solutions. One would be to move all the sql parameters to the class level of the data class and then store them in some sort of array that I set in the business layer. Any help would be useful!
So essentially you want to pass in a List of Parameters?
Why not redo your Commit function and have it accept a List of Parameter objects?
If your on SQL 2008 you can use merge to replace insert / update juggling. Sometimes called upsert.
You could create a struct to hold the parameter values.
Thanks for the responses, but I think I've figured out a better way for what I'm doing. It's similar to using the upsert, but what I do is have one method called Commit that looks for the given primary key. If the record is found in the database, then I execute an update command. If not, I do an insert command. Since the parameters are the same, you don't have to worry about changing them any.
For your problem I guess Iterator design pattern is the best solution. Pass in an Interface implementation say ICommitableValues you can pass in a key pair enumeration value like this. Keys are the column names and values are the column commitable values. A property is even dedicated as to return the table name in which to insert these value and or store procedures etc.
To save typing you can use declarative programming syntax (Attributes) to declare the commitable properties and a main class in middleware can use reflection to extract the values of these commitable properties and prepare a ICommitableEnumeration implementation from it.