I'm using Spring's JDBC support to run SQL queries and updates on an Oracle database. I'd like to insert a row and then get the key that it was assigned (using an Oracle sequence). In normal JDBC code, I would include a RETURNING INTO clause and then register an output parameter (well described here)
However, I would like to just use Spring to handle all my JDBC work for me. For non-insert SQL statements, I'm currently using a MapSqlParameterSource object and registering all my input parameters. Can I also register an output parameter like this and have it returned to me? I looked over the Chapter 11 portion of the Spring docs, and I saw there was support for an output parameter if I'm using stored procedures, but I would like to avoid doing that if possible. Thanks.
I don't think the Spring JDBC support API provides explicit support for OUT parameters, so you may need to step back a bit and use the more general query API provided by JdbcTemplate:
Object execute(PreparedStatementCreator psc, PreparedStatementCallback action)
This lets you perform arbitrary JDBC operations within the scope of a Spring-managed connection and PrepatedStatement. The downside is that the handling and tidyup of things like ResultSets becomes your problem.
Check out this code - it may do what you want, not sure if Oracle supports this syntax though.
getReturnedGeneratedKeys() Spring JDBC Excample
Related
I want to learn more about Spring JPA and what happens under the hood when a native JPA query (using PostgreSQL) is defined and called in a Repository class. I have tried searching online but all posts are related to defining and using native queries.
I am more interested to learn about what happens when my SpringBoot application calls a method that is annotated with #Query. I am mainly looking into this to try and understand the performance of executing such a query within Java.
Can anyone point me to a resource which goes in depth on what exactly happens under the hood when using Spring JPA?
Can anyone point me to a resource which goes in depth on what exactly happens under the hood when using Spring [DATA] JPA?
The authoritative source for this kind of information is the source.
Let me point you to some places of interest.
Basically the following happens:
find and extract the query from the annotation.
possibly create a count query from that.
replace spell expression with parameters.
add ordering if applicable.
prepare the query with the EntityManager.
register parameters.
add pagination limits.
execute the query.
transform result.
Output log to view what SQL query really generated and executed
For example, in application.properties:
logging.level.org.springframework.data.jpa=debug
logging.level.org.hibernate=debug
SpringBoot log reference
Check the source code of spring-data-jpa here:
https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java
I am using jOOQ to generate my SQL queries and I was wondering if there is a way to inject a condition in all the queries that my application does.
For example, I would like to have something like account = {accountNameHere} in all the SELECT that the application does. Since I already have a a high number of different queries, I would like to do that without manually adding the condition to each statement.
Is there a way to do that easily using jOOQ ? Maybe using the VisitListener ?
Yes, a VisitListener will be the most thorough way to inject a custom predicate into all of your SELECT statements (including subqueries, of course). In fact, what you're looking for is sometimes referred to as "row level security" (natively supported in RDBMS like Oracle or SQL Server).
The following blog post explains how to achieve this via a VisitListener:
http://blog.jooq.org/2015/06/17/implementing-client-side-row-level-security-with-jooq
Oracle provides a statement compiler hint, NO_COPY, that can be used to improve performance of SQL statements, particularly those that involve large data structures.
My problem is that, try as I might, I can't find any reference on how to use this feature through the Java API. All I can find is this javadoc for Oracle Fusion which, as I understand, is a separate middleware package that can be applied over the database layer (presumably at great expense), which is not what I need.
EDIT
I am fairly new to database programming and it is quite possible that I have missed something important here!
I am using CallableStatements to call a prepared statement already written in the database. Since I have to tell the Java API the type of each returned parameter with registerOutParameter(), I had assumed that I would also need to tell the Java API to use NO-COPY (ie if the JDBC driver can't work out the types from the procedure definition in the database, I figured I would need to tell it to use NO_COPY as well).
Have I got this all wrong?
NOCOPY is used when you declare and define a PL/SQL subprogram. You don't need to specify it when you call the procedure or function -- much like you don't specify the type or mode (IN/OUT) in a call.
I need to write pretty straight forward DB code and I'm considering MyBatis over plain JDBC (I believe full ORM is an overkill).
Considering that in both MyBatis and plain JDBC you find yourself:
Hand writing SQL statements.
Manually wiring DB rows to JAVA DTO objects (either via code or config).
The MyBatis benefits over JDBC I know of are:
Out-of-the-box table/query caching.
Dynamic SQL.
SQL is stored outside of the code.
Templating SQL for easier DB vendor Independence.
What other MyBatis-Over-JDBC benefits are there to consider?
I dont know you'll count this one as advantage or not but there's MyBatisGenerator, And It generates all basic needed Queries plus some Advanced Queries too and DTO objects automatically based on a single XML file.
Plus it has Eclipse Plugin For the same.
Most of the times you do not need to map explicity columns to pojos so bullet number 2 is a difference rather than a similarity.
The main difference IMHO is the API that is much simpler in MyBatis than in JDBC. If used with Spring or Guice you will not need to call MyBatis API in your code at all.
Mappers and injection helps the testing a lot because mappers are plain interfaces so easy to mock.
About : 'Manually wiring DB rows to JAVA DTO objects (either via code or config).'
This is not totally true, if you use conventions you can get an automatic mapping from DB tables to Java classes, example you have a CUSTOMER table that has fields like ID, COMPANY_NAME, PHONE_NUMBER, and a Java class Customer with properties id, companyName and phoneNumber, MyBatis is smart enough to figurate the DB to camel case convention and no mapping is required from you. Great!
MyBatis require less code and is cleaner than plain JDBC coding
MyBatis supports named parameters, JDBC supports only placeholders? (ugg!)
With a single line you can change from Reuse Prepared Statement Mode to Bath Mode, in plain JDBC it will take you a rewrite of your code.
I thought I knew everything about UDTs and JDBC until someone on SO pointed out some details of the Javadoc of java.sql.SQLInput and java.sql.SQLData JavaDoc to me. The essence of that hint was (from SQLInput):
An input stream that contains a stream
of values representing an instance of
an SQL structured type or an SQL
distinct type. This interface, used
only for custom mapping, is used by
the driver behind the scenes, and a
programmer never directly invokes
SQLInput methods.
This is quite the opposite of what I am used to do (which is also used and stable in productive systems, when used with the Oracle JDBC driver): Implement SQLData and provide this implementation in a custom mapping to
ResultSet.getObject(int index, Map mapping)
The JDBC driver will then call-back on my custom type using the
SQLData.readSQL(SQLInput stream, String typeName)
method. I implement this method and read each field from the SQLInput stream. In the end, getObject() will return a correctly initialised instance of my SQLData implementation holding all data from the UDT.
To me, this seems like the perfect way to implement such a custom mapping. Good reasons for going this way:
I can use the standard API, instead of using vendor-specific classes such as oracle.sql.STRUCT, etc.
I can generate source code from my UDTs, with appropriate getters/setters and other properties
My questions:
What do you think about my approach, implementing SQLData? Is it viable, even if the Javadoc states otherwise?
What other ways of reading UDT's in Java do you know of? E.g. what does Spring do? what does Hibernate do? What does JPA do? What do you do?
Addendum:
UDT support and integration with stored procedures is one of the major features of jOOQ. jOOQ aims at hiding the more complex "JDBC facts" from client code, without hiding the underlying database architecture. If you have similar questions like the above, jOOQ might provide an answer to you.
The advantage of configuring the driver so that it works behind the scenes is that the programmer does not need to pass the type map into ResultSet.getObject(...) and therefore has one less detail to remember (most of the time). The driver can also be configured at runtime using properties to define the mappings, so the application code can be kept independent of the details of the SQL type to object mappings. If the application could support several different databases, this allows different mappings to be supported for each database.
Your method is viable, its main characteristic is that the application code uses explicit type mappings.
In the behind the scenes approach the ResultSet.getObject(int) method will use the type mappings defined on the connection rather than those passed by the application code in ResultSet.getObject(int index, Map mapping). Otherwise the approaches are the same.
Other Approaches
I have seen another approach used with JBoss 4 based on these classes:
org.jboss.ejb.plugins.cmp.jdbc.JDBCParameterSetter
org.jboss.ejb.plugins.cmp.jdbc.JDBCResultSetReader.AbstractResultSetReader
The idea is the same but the implementation is non-standard (it probably pre-dates the version of the JDBC standard defining SQLData/SQLInput).
What other ways of reading UDT's in Java do you know of? E.g. what does Spring do? what does Hibernate do? What does JPA do? What do you do?
An example of how something similar to this can be done in Hibernate/JPA is shown in this answer to another question:
Java Enums, JPA and Postgres enums - How do I make them work together?
I know what Spring does: you write implementations of their RowMapper interface. I've never used SQLData with Spring. Your post was the first time I'd ever heard of or thought about that interface.