I connect with jdbc:postgresql://localhost:5432/mydatabase?currentSchema=myschema.
I have the following configuration for SimpleJdbcInsert. I use Spring Boot.
#Bean
#Qualifier("simpleJdbcInsert")
public SimpleJdbcInsert simpleJdbcInsert(#Qualifier("dataSource") DataSource dataSource) {
return new SimpleJdbcInsert(dataSource).withTableName("tableX").usingGeneratedKeyColumns("id");
}
But i get the following execption:
org.springframework.dao.DataAccessResourceFailureException: Unable to locate table meta data for 'tableX' in the default schema
I don't know why, because i thought that i set the currentSchema=myschema already.
I don't want to do following because i set the currentSchema=myschema in the JDBC URL above.
new SimpleJdbcInsert(dataSource).withSchemaName("Schema1").withTableName("tableX").usingGeneratedKeyColumns("id");
Related
I really want to try batching insert operations for myself in spring, but there is a huge problem that is driving me insane.
As written on web, Hibernate will silently disable batching queries whenever you have entity with GenerationType.IDENTITY (https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#batch-session-batch).
Therefore, I have tried to change my entities generationType to Sequence, but whenever i do this, my project seems to be completely broken (it won't even start).
I start to think that there are several problems in compatibility of postgresql and batching operations in spring.
Could you please explain to me, why is that?
My datasource configuration method:
#Bean
public DataSource dataSource() {
Properties props = new Properties();
props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
props.setProperty("dataSource.user", "tesstuser");
props.setProperty("dataSource.password", "12345");
props.setProperty("dataSource.databaseName", "testdatabase");
props.put("dataSource.logWriter", new PrintWriter(System.out));
HikariConfig config = new HikariConfig(props);
HikariDataSource dataSource = new HikariDataSource(config);
return ProxyDataSourceBuilder.create(dataSource)
.name("Batch-Insert-Logger")
.asJson().countQuery().logQueryToSysOut().build();
}
Error message:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
PostgreSql exception:
org.postgresql.util.PSQLException: ERROR: relation "hibernate_sequence" does not exist
Spring Boot : How to add new Datasource at runtime
My project want to connect two datasource.
The first datasource I can Config in application.properties but the second datasource can't config because this config is in the tableConfig from DB of the first datasource.
So,
config the 1st datasource.
query data from the 1st datasource for get config of 2nd datasource (url, username, password).
add new 2nd datasource
Now, I config two Datasource from application.properties and it's work.
But the requirement want to change the 2nd datasource from table of 1st datasource. T.T
Please, gives me some suggestions.
Thank you.
A Spring configuration like this should work (consider it pseudo code):
#Bean("secondDatasource")
public Datasource secondDatasource(#Qualifier("firstDatasource") Datasource ds){
// use `ds` to obtain the necessary information to obtain a datasource ...
return DataSourceBuilder
.create()
.username(username)
.password(pwd)
.url(url)
.driverClassName(driver)
.build();
}
I would at least start without using Spring Data JPA in the configuration class and operate directly on the data source to keep things simple.
You already got pointers, how to set up Spring Data JPA to then use the different data sources: http://www.baeldung.com/spring-data-jpa-multiple-databases
The code above is mainly just copied from: https://stackoverflow.com/a/28822145
I have mysql database and i have configured database properties in application.properties file .
Now if i do change db connection properties , i want reflect that changes into my application on the fly , means with out restarting the server
Is this possible using with spring cloud config server and actuator?
I have tested this quite a bit and here are my findings.
Spring config server works pretty well for simple key value pairs.
It also works for Database properties provided that you are creating datasource objects yourself and you are using #RefreshScope.
For example, if you have a config server with these properties.
mongodb.feed.database=kiran
mongodb.feed.host=localhost
mongodb.feed.port=27017
And you are configuring MongoTemplate in your application like this.
#Configuration
#ConfigurationProperties(prefix = "mongodb.feed")
#EnableMongoRepositories(basePackages = "in.phani.springboot.repository", mongoTemplateRef = "feedMongoTemplate")
#Setter
class FeedMongoConfig {
private String host;
private int port;
private String database;
#Primary
#Bean(name = "feedMongoTemplate")
#RefreshScope // this is the key
public MongoTemplate feedMongoTemplate() throws Exception {
final Mongo mongoClient = createMongoClient(new ServerAddress(host, port));
return new MongoTemplate(mongoClient, database);
}
Mongo createMongoClient(ServerAddress serverAddress) {
return new MongoClient(serverAddress);
}
}
And if you change the database name in your config properties and then refresh the scope with /refresh endpoint. It works pretty well.
With springboot you need not do manual configuration like this. Spring boot has Autoconfiguration for most of the stuff. Continuing with the same example above, if you were to put in config properties something like this
spring.data.mongodb.uri=mongodb://localhost:27017/phani
spring-boot will configure MongoTemplate for you(you don't need to create yourself as in 2nd point).
Here comes the hiccup.
Now if you change the database name, and refresh the scope, it doesn't work. Because in this case, MongoTemplate was configured by spring-boot Autoconfiguration(MongoAutoConfiguration)
So in conclusion, it needs extensive testing to be done, before using it on production(especially for complex beans like datasources, MongoTemplates), since there is not enough documentation on this.. But I would say, it is worth trying.
I'm using Spring and Hibernate with an automatically generated database (for that I have set "hibernate.hbm2ddl.auto" to "update" in the JPA configuration properties).
I also have a class annotated #Configuration with a #PostConstruct method that is called on application startup after the database has been created or updated. This is where I setup the database with some default data if it's empty (first launch).
I would like to execute some custom native SQL queries at this moment. These queries won't return anything, they're just configuration stuff (like creating additional indexes or extensions).
Currently I'm stuck on creating a SessionFactory in order to create a new Hibernate Session. I've tried auto wiring it, but it doesn't work :
#Autowired
SessionFactory sessionFactory;
Gives me: Field sessionFactory in ... required a bean of type 'org.hibernate.SessionFactory' that could not be found.
I understand that I probably need to configure it elsewhere, but I don't know where. Several answers on SO use an xml configuration file, but I'm not using any configuration file so I can't do it that way.
Is there a way Spring can create the SessionFactory with the appropriate configuration ?
You don't even need to access SessionFactory. Please just put your scripts into a file src/main/resources/scripts/myscript.sql. You can then do the following with Spring:
#Component
public class Startup {
#Autowired
private DataSource dataSource;
#PostConstruct
public void runNativeSql() {
ClassPathResource resource = new ClassPathResource("scripts/myscript.sql");
try(Connection connection = dataSource.getConnection()) {
ScriptUtils.executeSqlScript(connection, resource);
} catch (SQLException | ScriptException e) {
//LOG
}
}
}
You can autowire the JPA EntityManager as:
#PersistenceContext
EntityManager entityManager;
If you really need a Hibernate Session and are using using JPA 2.1, the Session can be obtained from the EntityManager as:
entityManager.unwrap(Session.class);
I would like to get a datasource from a hibernate Configuration programmaticaly. Here is the code that I wrote :
public static DataSource getDatasource(Configuration configuration){
ServiceRegistry registry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
SessionFactoryImpl session = (SessionFactoryImpl)configuration.buildSessionFactory(registry);
DatasourceConnectionProviderImpl provider = (DatasourceConnectionProviderImpl) session.getConnectionProvider();
return provider.getDataSource();
}
But I got an exception while running the application :
Exception in thread "main" org.hibernate.HibernateException: Missing table: CONTACTS
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1281)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:155)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:508)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1769)
at com.heavenize.Migrations.getDatasource(Migrations.java:30)
at com.heavenize.Migrations.main(Migrations.java:60)
I am performing some database migration and I need the datasource to pass to my migration tool programmaticaly.
It seems that problem come with the fact that buildSessionFactory because hibernate is trying to map the entities with the tables in the database.
The property "hibernate.hbm2ddl.auto" is set to validate.
Is there a better way to get the datasource?
The error that you are getting has nothing to do with retrieving the DataSource. It is because Hibernate is validating the data model with the database and doesn't find it to be in syncrhonization. You can remove the hibernate.hbm2ddl.auto property completely, which will then default it to none and there won't be any validation.