What is the main difference between Spring JDBC VS JDBC?
Let me show you some simple example using JDBC:
final Connection connection = ds.getConnection();
try {
final Statement statement = connection.createStatement();
try {
final ResultSet resultSet = statement.executeQuery("SELECT COUNT(*) FROM Orders");
try {
resultSet.next();
final int c = resultSet.getInt(1);
} finally {
resultSet.close();
}
} finally {
statement.close();
}
} finally {
connection.close();
}
It's much better when try-with-resources though:
try (
Connection connection = ds.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT COUNT(*) FROM Orders");
) {
resultSet.next();
final int c = resultSet.getInt(1);
}
Of course you can extract common code and use template method Design Pattern. Effectively you'd reinvent JdbcTemplate:
final int c = new JdbcTemplate(ds).queryForInt("SELECT COUNT(*) FROM Orders");
Also Spring JDBC provides exception translation (no more checked SQLException and differences between databases/dialects) and simple ORM capabilities.
Spring JDBC value-add provided by the Spring Framework's on top JDBC layer
Define connection parameters
Open the connection
Specify the statement
Prepare and execute the statement
Set up the loop to iterate through the results (if any)
Do the work for each iteration
Process any exception
Handle transactions
Close the connection
Basically , you don't need to worry about managing and suffering from infrastructure/plumbing code and purely worry about data and its mapping to objects.
Spring utilizes Template pattern to hide all low level details while giving you extension hooks to extend and work with JDBC.
Also, there is a well defined API for database exceptions, that is really developer-friendly when compared to exception hierarchy provided by low level JDBC API's
1.) Spring jdbc module is an abstraction layer on top of jdbc technology, this layer avoids the boiler plate code used in jdbc programming.
2.) Spring ORM module is an abstraction layer on top ORM tools.
3.) When working with ORM tools like a hibernate again we have a Boiler plate code this spring ORM layer avoids boiler plate code of ORM tools.
Spring JDBC? I only know of a couple of Spring JDBC Templates.
They allow you to access JDBC functionality from within Spring container, and they provide some additional simplifications compared to plain JDBC, like connection management and exception handling.
Basically Spring is harder to setup but easier to develop with, so it all depends on the scope of the problem you're dealing with.
In my opinion, JDBC shares some functionalities with JDBCTemplate, but they can be quite different. The main differences that come to my mind at the first glance at this question are:
If you are handling a huge amount of data, say you want to insert into a database millions(or billions) of rows of records, you might want to use JDBC. In less than 4 minutes I inserted one million rows with different information into the database with JDBC and MySQL statements concatenation. In contrast, it will take me probably more than ten minutes to do the same thing with JDBC Template.
However, if you are using JDBC, more codes must be written to get things right, compared to the use of JDBC Template. Tomasz Nurkiewicz has illustrated this point by code and Santosh Gokak has provided a summary of steps to use JDBC. But there's one more thing implicit behind the scene, and that is the configuration of Spring, since JDBC Template is a part of Spring Framework. If you are new to XML/Annotation configuration for Spring, things might be a little complicated, while JDBC, though requiring more steps, is to some extent more intuitive.
Related
im running Checkmarx on my code and im getting an sql injection vulnerability.
this is the simplified method im using
public String assignRole(String userId, String roleId) {
Optional<RoleEntity> roleEntity = roleRepository.findById(roleId)
if (roleEntity.isPresent()) {
UserEntity user = UserEntity.builder().userId(userId).role(roleEntity.get()).build();
userRepository.save(user);
return "SUCCESS";
} else {
throw new ServiceException("ERROR");
}}
and the analysis of checkmax says:
The application's assignRole method executes an SQL query with save, at line xx of
src/Service.java. The application
constructs this SQL query by embedding an untrusted string into the query without proper sanitization. The
concatenated string is submitted to the database, where it is parsed and executed accordingly.
An attacker would be able to inject arbitrary syntax and data into the SQL query, by crafting a malicious
payload and providing it via the input roleId;
This may enable an SQL Injection attack.
im a little bit confused because im not building a native query or concatenating strings in a query, or maybe im missing something.
any ideas for fix this? or maybe is a false positive.
This sounds like a false positive.
If your Java code uses Spring, I recommend configuring your scan (Settings > Scan Settings > Preset Manager) with the SQL_Injection and Second_Order_SQL_Injection items under the Java section disabled (unchecked) to avoid false positives from these items.
If your code persists data to the database exclusively via the Spring save action, it is not at risk of SQL injection exploitation. That’s because Spring saves (inserts or updates) to the database using an object mapped to your db (the ORM approach) which does not allow additional sql to be maliciously forced in.
Nonetheless, from what I’ve seen, Checkmarx marks Spring save actions, falsely, as high severity SQL Injection vulnerabilities (SQL_Injection and/or Second_Order_SQL_Injection). Given this, disabling those rules seems to me valid and in fact the only viable way around this.
But if you do take this approach, make sure your code does not for some reason also use some other some other sql approach such as a String containing SQL that’s not sanitized via the use of PreparedStatement. Those statements are vulnerable to sql injection exploits and I believe are what the Checkmarx SQL injection rules are intending to identify.
I have a system that uses a Oracle database, with a schema that is different from the application user. The schema name itself is not known in advance, so we can't just hardcode it. It's a system property.
Most of the data access is through Hibernate, which can specify the default schema on connection so this is not a problem in those cases.
However, there are a few places where plain SQL queries are used (using spring jdbcTemplate). So right now we have something that boils down to:
Map<String,Object> result = jdbcTemplate.queryForMap("SELECT A, B, C FROM "+schema+".TABLE WHERE blablablah");
And this, of course, is an open SQL injection vulnerability. We're planning security audits and this will be flagged for sure.
So the question is: How do I specify the schema on the query, be it with jdbcTemplate, another Sprint data access utility, or even plain jdbc?
Thank you,
JGN
You can use Connection.setSchema to specify the schema for a JDBC connection. This should be done before you create the Statement to execute a SQL command.
With Spring JPA is there an easy way to use native queries but maintaining database independence, for example by using the query which fits best?
At the moment I do this by checking the currently set Dialect from the Environment and call the proper method of my Repository:
public Foo fetchFoo() {
if (POSTGRES_DIALECT.equals(env.getRequiredProperty("hibernate.dialect"))) {
return repo.postgresOptimizedGetFoo();
}
return repo.getFoo();
}
This works but I have the feeling that there is a better way or that I am missing something. Especially because (Spring) JPA allows it to use native queries quite easily but that breaks one of its big advantages: database independence.
As per my understanding, this can be achieved simply by using #Transactional(readOnly=false) and then instead of calling session.createQuery, one can use session.createSQLQuery, as provided in this example.
Your sql can be any of your native query.
Hope this works for you. :)
#Override
#Transactional(readOnly = false)
public Long getSeqVal() {
Session session = entityManager.unwrap(Session.class);
String sql = "SELECT nextval('seqName')";
Query query = session.createSQLQuery(sql);
BigInteger big = (BigInteger) query.list().get(0);
return big.longValue();
}
This is just an idea: I do not know whether it works or not:
My idea would be having subinterfaces, one normal Spring-Data-JPA-interface with all methods for one entiy (without native query hints). Than I would crate a subinterface for every database, that "override" the database specific native statements. (This intrface would be empty if there are no DB specific statements). Then I would try configure Spring-JPA with some profiles to load the right specific interface (for example by a class-name or package-name-pattern)
This seems like a way to complicated way to get queries to work.
If you really want to use optimized queries make it at least transparant for your code. I suggest using named queries and create an orm.xml per database (much like Spring Boot uses to load the schema.xml for a different database).
In your code you can simply do
public interface YourRepository extends JpaRepository<YourEntity, Long> {
List<YourEntity> yourQueryMethod();
}
This will look for a named query with the name YourEntity.yourQueryMethod. Now in your orm.xml add the named query (the default one and in another one the optimized one).
Then you need to configure your LocalContainerEntityManagerFactory to load the specific one needed. Assuming you have a property defining which database you use, lets name it database.type you could do something like the following
<bean class="LocalContainerEntityManagerFactoryBean">
<property name="mappingResources" value="classpath:META-INF/orm-${database.type}.xml" />
... other config ...
</bean>
This way you can keep your code clean of the if/then/else construct and apply where needed. Cleans your code nicely imho.
I wanted to use Ormlite in my java project so I created two beans :
#DatabaseTable(tableName = "worker")
public class Worker {
#DatabaseField(columnName="wo_id" , generatedId=true , id=true)
private Integer woId;
#DatabaseField(columnName="wo_nom")
private String woNom;
}
#DatabaseTable(tableName = "qualification")
public class Qualification {
#DatabaseField(columnName="qu_id" , generatedId=true , id=true)
private Integer quId;
#DatabaseField(columnName="qu_nom")
private String quNom;
}
When creating the tables, I figured out (too late maybe?) that I needed SQLlite or something like that...
Is it possible to create and use a database from my Java project without using JDBC or anything else of the kind?
without using JDBC or anything else of the kind
JDBC is the way that Java interacts with databases of any kind unless you care to write your own database driver. Assuming you don't want to do that and what you're really looking for is an in-memory or file-based database, use H2. It's superior to both HSQL, which is its predecessor, and Derby.
#RyanStewart is correct that if you are talking about connecting to a SQL database, the was to do with is through JDBC which is how Java communicates with SQL databases like H2, Sqlite, MySQL, Postgres, Derby, etc.. All of those database types are supported by ORMLite.
Is it possible to create and use a database from my Java project without using JDBC or anything else of the kind?
Just for posterity, one way to use ORMLite without JDBC is to implement the backend database interfaces:
ConnectionSource
DatabaseConnection
CompiledStatement
DatabaseResults
This would allow you to implement a backend. But I suspect that you should use JDBC but maybe this information is helpful to others.
An in memory database : http://db.apache.org/derby/
You can use HSQLDB.
HSQLDB - 100% Java Database
Running and Using Hsqldb
i want to use prepared statement with ejb3 to insert data in oracle. is it possible to use.
i try to find some example on net but i could not find any good example.
Please help me to use it. or is there any other way to use parameter query (as we use ? in prepared statement) in ejb3
Thanks and regards
it is very simple:
public class YourEJB {
#Resource(mappedName="java:/DefaultDataSource")
DataSource dataSource;
// XXX: not handling exceptions
public void insertPerson(String name, String surname) {
Connection connection = dataSource.getConnection();
PreparedStatement insertPerson = connection.prepareStatement(
"INSERT INTO PEOPLE VALUES(?,?)");
insertPerson.setString(1, name);
insertPerson.setString(2, surname);
insertPerson.executeUpdate();
}
Take also a look at JDBC tutorials.
If you're using EJB, the idiom is to use entity beans for database interaction. If you're using EJB3, you should be creating an object and using annotations to deal with the database. SQL is generated for you using JPA.
So if EJB is providing all that abstraction to help you, why do you feel the need to go back to the lower level and write a PreparedStatement? Maybe the real answer is to rethink your object model and see how the query could fit into an entity bean abstraction.