I want to use jooq on a server where the DB environment is dynamic - spring

I want to use jooq on a server where the DB environment is dynamic.
I want to use jooq in spring boot 2 gradle environment.
But there is a problem.
The build.gradle file requires hard-coded DB information but is available.
Can I create only JClass like QClass in QueryDSL?
I am in the server's external environment
Creates a dynamic DataSource such as ClassName, UserName, Password, and URL.
Hard-coded jooq can not be used.
In jooq
jooq{
version = '3.11.2'
sample(sourceSets.main) {
jdbc {
driver = 'org.postgresql.Driver'
url = 'jdbc:mysql//localhost:3306/sample'
user = 'some_user'
password = 'secret'
....
===========
The jdbc connection information should be hard-coded as shown.
But I want a dynamic jooq setting based on the external server settings.
Generally, a dynamic DataSource generation method is already in use.
Help!
I'm sorry I did not speak English.

You can build datasource in your configuration class instead of having hardcoded values in application.yml. Something like this:
#Bean
private DataSource buildDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(env.getProperty("dataSource.url")+ "_somevalue");
dataSource.setUsername(env.getProperty("dataSource.username"));
dataSource.setPassword(env.getProperty("dataSource.password"));
return dataSource;
}
so you can define datasource url,username,password using some logic.

Related

springboot + JDBTemplate (No datasource specified error even though specified in application.properties

Application.properties
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=
i placed this application.properties in resources folder.
Java Class
#Component
public class data{
#Autowired
private JdbcTemplate jdbcTemplate;
public void queryData(){
String sql = "select * from DEPOSIT";
jdbcTemplate = new JdbcTemplate();
jdbcTemplate.execute(sql);
}
}
I am getting
java.lang.Illegal Argument Exception:No Data Source Specified
I am getting this error message even though i specified data source in application.properties
I am using Spring Boot for this task. I Have added almost all the dependencies required in POM.
Not sure why i am not able to access data source. basically trying to access data from DB using Spring boot, MySQL, jdbcTemplate.
Not sure whats wrong here.
Do i have to add anything in the code so that data source can be specified in java class?
Add below properties to your application.properties file. This specifies the data source for your application. Do check if mysql is running on your machine before starting your application.
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
For additional information refer to below link:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html

Completely auto DB upgradable Spring boot application

I am trying to use flyway for DB migrations and Spring boot's flyway support for auto-upgrading DB upon application start-up and subsequently this database will be used by my JPA layer
However this requires that schema be present in the DB so that primary datasource initialization is successful. What are the options available to run a SQL script that will create the required schema before flyway migrations happen.
Note that If I use flyway gradle plugin (and give the URL as jdbc:mysql://localhost/mysql. It does create the schema for me. Am wondering if I could make this happen from Java code on application startup.
Flyway does not support full installation when schema is empty, just migration-by-migration execution.
You could though add schema/user creation scripts in the first migration, though then your migration scripts need to be executed with sysdba/root/admin user and you need to set current schema at the beginning of each migration.
If using Flyway, the least problematic way is to install schema for the first time manually and do a baseline Flyway task (also manually). Then you are ready for next migrations to be done automatically.
Although Flyway is a great tool for database migrations it does not cover this particular use case well (installing schema for the first time).
"Am wondering if I could make this happen from Java code on application startup."
The simple answer is yes as Flyway supports programmatic configuration from with java applications. The starting point in the flyway documentation can be found here
https://flywaydb.org/documentation/api/
flyway works with a standard JDBC DataSource and so you can code the database creation process in Java and then have flyway handle the schema management. In many environment you are likely to require 2 steps anyway as the database/schema creation will need admin rights to the database, while the ongoing schema management will need an account with reduced access rights.
what you need is to implement the interface FlywayCallback
in order to kick start the migration manually from you code you can use the migrate() method on the flyway class
tracking the migration process can be done through the MigrationInfoService() method of the flyway class
Unfortunately if your app has a single datasource that expects the schema to exist, Flyway will not be able to use that datasource to create the scheme. You must create another datasource that is not bound to the schema and use the unbounded datasource by way of a FlywayMigrationStrategy.
In your properties file:
spring:
datasource:
url: jdbc:mysql://localhost:3306/myschema
bootstrapDatasource:
url: jdbc:mysql://localhost:3306
In your config file:
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean
#ConfigurationProperties("spring.bootstrapDatasource")
public DataSource bootstrapDataSource() {
return DataSourceBuilder.create().build();
}
And in your FlywayMigrationStrategy file:
#Inject
#Qualifier("bootstrapDataSource")
public void setBootstrapDataSource(DataSource bootstrapDataSource) {
this.bootstrapDataSource = bootstrapDataSource;
}
#Override
public void migrate(Flyway flyway) {
flyway.setDataSource(bootstrapDataSource);
...
flyway.migrate()
}

How to disable H2's DATABASE_TO_UPPER in Spring Boot, without explicit connection URL

I'm aware that H2 has a boolean property/setting called DATABASE_TO_UPPER, which you can set at least in the connection URL, as in: ;DATABASE_TO_UPPER=false
I’d like to set this to false, but in my Spring Boot app, I don’t explicitly have a H2 connection URL anywhere. Implicitly there sure is a connection URL though, as I can see in the logs:
o.s.j.d.e.EmbeddedDatabaseFactory: Shutting down embedded database:
url='jdbc:h2:mem:2fb4805b-f927-49b3-a786-2a2cac440f44;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
So the question is, what's the easiest way to tell H2 to disable DATABASE_TO_UPPER in this scenario? Can I do it in code when creating the H2 datasource with EmbeddedDatabaseBuilder (see below)? Or in application properties maybe?
This is how the H2 database is explicitly initialised in code:
#Configuration
#EnableTransactionManagement
public class DataSourceConfig {
#Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("db/init.sql", "db/schema.sql", "db/test_data.sql")
.build();
}
}
Also, I'm telling JPA/Hibernate not to auto-generate embedded database (without this there was an issue that two in-memory databases were launched):
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
You can't w\ the generateUniqueName, but if you call setName("testdb;DATABASE_TO_UPPER=false") you can add parameters. I doubt this is officially supported, but it worked for me.
The spring code that generates the connection url is like this:
String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false", databaseName)
You may want abandon using explicit creation via EmbeddedDatabaseBuilder. Spring Boot creates H2 instance automatically based on configuration. So I would try this in application.properties:
spring.datasource.url=jdbc:h2:file:~/testdb;DATABASE_TO_UPPER=false

writing API's with JPA

In a big company, our team provides API's for accessing data on a oracle DB. Until now, we used plain SQL (JDBC) to get/write the data on the database.
So most of the existing API's looked like this (ok, not always that stupid :-)
public class DummyApi {
private final DataSource datasource;
public DummyApi(javax.sql.DataSource datasource) {
this.datasource = datasource;
}
public void doSomething() throws SQLException {
Connection connection = datasource.getConnection();
PreparedStatement statement = connection.prepareStatement("plain sql query");
statement.execute();
}
}
Using such API's is simple, it doesn't matter if your end-application is plain java SE, spring or javaEE. Further, transaction-APIs works proper with this API's. We use them with spring TransactionManager (together with the TransactionAwareDataSourceProxy) and with JTA in CMA-Java EE applications.
Now we evaluate to use JPA in new API's. And the big question we currently struggle is the following: how can we provide a simple interface so that the end-application doesn't need to know about JPA? How can we initialize the EntityManager with a DataSource (for example provided as constructor parameter)? And how can we rollback if there are old, plain JDBC-APIs AND new JPA-APIs in the same transaction (begin/rollback in the end-application)?
Thanks for bringing a little light on the matter!
With JPA the datasource will normally be set in the persistence.xml. If you need some sort of dynamic datasources, then you can pass the DataSource as a property to Persistence.createEntityManagerFactory().
Most JPA providers provide a way to get the JDBC Connection if you want to mix JDBC. Normally this is accessed using em.unwrap(Connection.class). You could also use JTA or Spring to have the transaction share the same connection.

Generate schema in dropwizard-hibernate

I followed the tutorial for dropwizard and hibernate without problems. Now I have non trivial annotations in my entities, and I would like hibernate to generate the tables for me, and stuff like that.So, how can I change hibernate's configuration? Can I give it a hibernate.cfg.xml? If I can, do I have to set up the connection again?
I found this PR,
but it doesn't seem to be in the public release yet (no hibernateBundle.configure in my jars)
But maybe I'm looking for the wrong thing. So far, I'm just trying to set hibernate.hbm2dll.auto. After all, there might be an other way to enable hibernate table generation in Dropwizard... So, any help?
Thank you.
Edit: I approached the problem from another angle, to explicitly create the schema instead of using hbm2ddl.auto. See proposed answer.
Edit: Problem solved! Doing this in the YAML config currently works: (Dropwizard 0.7.1)
database:
properties:
hibernate.dialect: org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto: create
(from this answer)
Old answer:
This is what I am currently using: A class that calls hibernate's SchemaExport to export the schema to a SQL file or to modify the database. I just run it after changing my entities, and before running the application.
public class HibernateSchemaGenerator {
public static void main(String[] args) {
Configuration config = new Configuration();
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.connection.url", "jdbc:mysql://localhost:3306/db");
properties.put("hibernate.connection.username", "user");
properties.put("hibernate.connection.password", "password");
properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.put("hibernate.show_sql", "true");
config.setProperties(properties);
config.addAnnotatedClass(MyClass.class);
SchemaExport schemaExport = new SchemaExport(config);
schemaExport.setOutputFile("schema.sql");
schemaExport.create(true, true);
}
}
I didn't know about hibernate tools before. So this code example can be used in the service initialization to act like hbm2ddl.auto = create.
I'm currently using it just by running the class (from eclipse or maven) to generate and review the output SQL.

Resources