Let's say I have an existing DataSource to a master database. I now need to create a new database, and execute some DDLs on that database. Is this possible with e.g, "USE" command, or do I need to create a new DataSource with the name of the new database in the JDBC url?
You can run the "USE" command as a regular JDBC statement.
Statement stmt = connection.createStatement();
stmt.execute("USE the_other_db");
Dependending on your DBMS and driver you might also be able to use the JDBC API call setCatalog():
connection.setCatalog("the_other_db")
The USE statement works, but since it's stateful, you have to make sure that it's part of the same connection as the latter statements.
If you use Spring's JdbcTemplate instead of working with java.sql.Connection and java.sql.Statement directly, you can use a SingleConnectionDataSource.
Related
There is something I don't understand :
Is Hibernate a DB manager and not only ORM?
My question: I have SpringBootApplication and use hibernate for connection to database and ORM aspect. In my mind, connection to DB is continuous.
On another hand, I want a puncual on-demand connection to an access DB, so I used simple java.sql.* library :
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Connection connection = DriverManager.getConnection("jdbc:ucanaccess://myDB.mdb", login, password);
This works but in order to not map manually each result query to a domain object, I would like to use hibernate to do :
getCurrentSession()
.createSQLQuery( "select e.id as id,e.first_name as firstName,e.password as password from xxxxxx")
.addScalar("id",StandardBasicTypes.INTEGER )
.addScalar("firstName",StandardBasicTypes.STRING )
.addScalar("password",StandardBasicTypes.STRING )
.setResultTransformer(Transformers.aliasToBean(Employee.class))
.list();
in order to have query result automatically bind to DOmain object.
BUT this is only available for hibernate library, not java.sql (or I didn't find).
SO should I have a second hibernate connection but not permanent so not configured in application.properties/hibernate.properties and so not managed by Spring (in order to have punctual connection)? In my mind, I would like to do something identical to java.sql previous example but with hibernate.
You will understand that I think I miss something about hibernate philosophy.
Thank you.
All I have implemented multitenancy with mysql and hibernate but I have doubts that it will work in real world.
As per following quote from hibernate document it should be possible:
Connections could point to the database itself (using some default schema) but the Connections would be altered using the SQL SET SCHEMA (or similar) command. Using this approach, we would have a single JDBC Connection pool for use to service all tenants, but before using the Connection it would be altered to reference the schema named by the “tenant identifier” associated with the currently logged in user.
Here is the link from where I got above paragraph.
Multitenancy in hibernate
So I override the MultiTenantConnectionProvider as below
#Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
Connection tenantSpecificConnection = dataSource.getConnection();
if (!StringUtils.isEmpty(tenantIdentifier)) {
Statement statement = tenantSpecificConnection.createStatement();
statement.executeQuery("use " + tenantIdentifier);
statement.close();
tenantSpecificConnection.setSchema(tenantIdentifier);
} else {
tenantSpecificConnection.setSchema(Constants.DEFAULT);
}
return tenantSpecificConnection;
}
It is very basic iteration, a first one, I am just able to switch the database. But with this I also have questions. Would this work in real world? I think multiple users will cause trouble while using this? According to hibernate documentation it should not but it looks it may cause problems. Has anyone tried this, please need help on this one.
I'm using Spring and JDBC template to manage database access, but build the actual SQL queries using JOOQ. For instance, one DAO may look like the following:
public List<DrupalTaxonomyLocationTerm> getLocations(String value, String language) throws DataAccessException {
DSLContext ctx = DSL.using(getJdbcTemplate().getDataSource(), SQLDialect.MYSQL);
SelectQuery q = ctx.selectQuery();
q.addSelect(field("entity_id").as("id"),);
q.addFrom(table("entity").as("e"));
[...]
}
As you can see from the above, I'm building and executing queries using JOOQ. Does Spring still take care of closing the ResultSet I get back from JOOQ, or do I somehow "bypass" Spring when I access the data source directly and pass the data source on to JOOQ?
Spring doesn't do anything with the objects generated from your DataSource, i.e. Connection, PreparedStatement, ResultSet. From a Spring (or generally from a DataSource perspective), you have to do that yourself.
However, jOOQ will always:
close Connection objects obtained from a DataSource. This is documented in jOOQ's DataSourceConnectionProvider
close PreparedStatement objects right after executing them - unless you explicitly tell jOOQ to keep an open reference through Query.keepStatement()
close ResultSet objects right after consuming them through any ResultQuery.fetchXXX() method - unless you explicitly want to keep an open Cursor with ResultQuery.fetchLazy()
By design, jOOQ inverses JDBC's default behaviour of keeping all resources open and having users tediously close them explicitly. jOOQ closes all resources eagerly (which is what people do 95% of the time) and allows you to explicitly keep resources open where this is useful for performance reasons.
See this page of the jOOQ manual for differences between jOOQ and JDBC.
Currently I made a connection to a database in this way:
MyClass.java
try {
DataSource datasource = JNDILoader.getDataSourceObject(pathToSource);
Class.forName("net.sourceforge.jtds.jdbc.Driver");
connection = datasource.getConnection();
stmt = connection.prepareStatement("{call storageProcedureXXX(?,?)}");
stmt.setString(1, "X");
stmt.setString(2, "Y");
result = stmt.executeQuery();
}catch (SQLException){
//TODO
}catch(Exception){
//TODO
}
That works for 1 class that makes the requests for the data, but , would be better if I create a singleton class and get the connection from it? (performance?, maintenability?, simplicity?). Which option would be better: Singleton vs StorageProcedures per each request?.
Note: At the end, the application (Restful Web Service) will need to connect to different databases to load data for different specialized classes, even , the classes would need loads data from plain text.
First of all you are mixing two different things: singleton and stored procedures. Singleton is design pattern, and stored procedures are procedures executed on database, typically encapsulating some business logic.
What you wrote is not really preferred way of connecting to database. If you have many request and create one connection for each request son you will have problems with too many connections to database. You should use connection pool. The most famous for Java is DBCP. Another one is c3p0.
For connection on different databases you should use something like Hibernate.
Stored procedure are executed on the database. You pass/retrieve data to/from it through the connection.
You have to check if it is thread safe (I don't think so), if you'll do concurrent calls or not.
Generally a stored procedure = 1 transaction happening in the database.
Why are you using stored procedure in the 1st place?
Named parameters, just like JdbcTemplate from Spring
XML configuration for JDBC connection settings
XML configuration for queries. Something like Hibernate <sql-query>. See Named SQL queries for an example
I'm thinking of trying to build my own, but I thought I'd ask here, maybe it's already been done.
Obviously I don't want to use neither an ORM nor JdbcTemplate.
What about MyBatis?
(source: mybatis.org)
I'am looking for the same thing, meanwhile try out DBUtils Utility:
http://commons.apache.org/dbutils/
Lightweight, open source and no dependencies.
Try JdbcSession from jcabi-jdbc. It's simple (as you want) and requires you to create a java.sql.DataSource before, for example (using BoneCP and H2 database):
BoneCPDataSource source = new BoneCPDataSource();
source.setDriverClass("org.h2.Driver");
source.setJdbcUrl("jdbc:h2:mem:x");
String name = new JdbcSession(source)
.sql("SELECT name FROM user WHERE id = ?")
.set(555)
.select(new SingleHandler<String>(String.class));