Point #Configuration file to hbm.xml - java

I have a library that contains a few objects I would like to save in my database using hibernate.
I ended up making hbm.xml files for every single object. Now I have my AppConfig class
#Configuration
#ComponentScan("some.company")
#EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)
#EnableTransactionManagement
public class AppConfig
extends WebMvcConfigurerAdapter
{
#Bean(name = "dataSource")
public DataSource dataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/somedatabase");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory()
{
LocalSessionFactoryBean localSession = new LocalSessionFactoryBean();
localSession.setDataSource(dataSource());
return localSession;
}
#Bean(name = "transactionManager")
public HibernateTransactionManager transactionManager()
{
return new HibernateTransactionManager(sessionFactory().getObject());
}
}
How do I point it to my newly created hbm.xml files?
Or if that is not possible, then how would I go about creating hibernate mapping for the objects to which I have no write access to?The only constraint is that I can not write my app config in xml, there is too much there that would not be movable to xml now.

Pragmatically, I would go for:
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean localSession = new LocalSessionFactoryBean();
localSession.setDataSource(dataSource());
localSession.setMappingResources("my.hmb.xml", "files.hbm.xml");
return localSession;
}
(when the hbm files reside in the root of class path - e.g. in src/main/resources)

Related

Unwanted empty table created in datasource

When I am trying to use multiple datasources in my Spring Boot Application, every entityManager is creating unwanted tables from other datasources. How can I fix this?
Here's related snippet of my code:
dataSourceConfig.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef= "entityManagerFactory",
basePackages= {"com.wnp.customerinfo.customerinfo.customerrepository"},transactionManagerRef="transactionManager")
public class CustomerConfig {
#Bean(name="datasource")
#ConfigurationProperties(prefix="spring.customer.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name="entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder,
#Qualifier("datasource") DataSource dataSource) {
Map<String,Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
return builder.dataSource(dataSource).properties(properties)
.packages("com.ecom.customerinfo.customerinfo.model").persistenceUnit("CustomerInfo").build();
}
#Bean(name="transactionManager")
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
application.properties
spring.customer.datasource.jdbcUrl=jdbc:mysql://localhost:3306/customer_info_db_temp
spring.customer.datasource.username=root
spring.customer.datasource.password=
spring.prod.datasource.jdbcUrl=jdbc:mysql://localhost:3307/prod_info_db_temp
spring.prod.datasource.username=root
spring.prod.datasource.password=
The configuration you used in the class is perfect. But if you have all the model classes in the same package and giving the same base-package in all the configuration classes it will always create the empty tables in all the databases. Try to keep them in different packages.

Spring and Hibernate with multiple databases

Good evening,
what is the correct and common approach of handling two or more databases?
Consider this HibernateConfiguration class configuring only one datasource:
#Configuration #EnableTransactionManagement
#PropertySource(value = { "classpath:hibernate.properties" })
public class HibernateConfiguration {
#Autowired
private Environment env;
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// ... setting data source
return dataSource;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
// ... setting Hibernate properties
return properties;
}
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(getDataSource());
sessionFactory.setPackagesToScan(new String[] { "POJOs'" });
sessionFactory.setHibernateProperties(getHibernateProperties());
return sessionFactory;
}
#Bean public HibernateTransactionManager transactionManager(SessionFactory sf) {
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sf);
return htm;
}
}
Is recommended to let one class configure one datasource? Or is enough to configure all at once? How do I specify in Dao class which SessionFactory will be used and what is the recommended approach in case of switching two exact same databases on two different hosting servers?
The example DAOs. First I need to switch between Foo and Bar.
#Repository
public class RepositoryImpl implements RepositoryDao {
#Autowired // Here I need to switch between databases "foo" and "bar"
private SessionFactory sessionFactory;
...
The second one I need fixed on example database Foo.
#Repository
public class FooImpl implements FooDao {
#Autowired // Here I need fixed on "Foo"
private SessionFactory sessionFactory;
One approach
#Bean
#Primary
#ConfigurationProperties("app.datasource.foo")
public DataSourceProperties fooDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("app.datasource.foo")
public DataSource fooDataSource() {
return fooDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean
#ConfigurationProperties("app.datasource.bar")
public BasicDataSource barDataSource() {
return (BasicDataSource) DataSourceBuilder.create()
.type(BasicDataSource.class).build();
}
Spring multiple datasources config
Other approach could be : loading different mapping (orm.xml) from persistence.xml or refer to different schemas in Entity classes.

Extending java configuration in spring

I m newbie on the spring and I m just testing some utilities to learn java configuration on the spring framework,so question is
I have two configuration as seen below and I want to extend one configuration to another and use sub java configuration with appconfig so I did this way and working everything good but I m still feeling its not good approach for me ,could you give me correct way on this or alternative of this thanks
Hibernate Configuration
**package configuration**
#Configuration
#EnableTransactionManagement
#ComponentScan({"configuration"})
#PropertySource(value={"classpath:application.properties"})
public class HibernateConfiguration {
#Autowired
Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(generateDataSource());
sessionFactoryBean.setPackagesToScan(new String[]{"whateverpackage.model"});
sessionFactoryBean.setHibernateProperties(generateProperties());
return sessionFactoryBean;
}
#Bean
public DataSource generateDataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverclassname"));
driverManagerDataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
driverManagerDataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
driverManagerDataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return driverManagerDataSource;
}
public Properties generateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory); //constructor-arg can be use in xml
return transactionManager;
}
}
SubConfiguration
package another.configuration
#Configuration
#ComponentScan({"another.configuration"})
#EnableTransactionManagement
#PropertySource(value={"classpath:application.properties"})
public class SubConfiguration extends HibernateConfiguration{
}
AppConfig
package another.configuration
#Configuration
#ComponentScan(basePackages="root package")
#Import(SubConfiguration.class)
public class AppConfig {
}

Spring & Hibernate without jpa

For my new project I plan to use Hibernate 5 and Spring 4 and as always like to separate into different layers / projects.
Gradle dependencies:
"org.springframework:spring-webmvc:4.2.1.RELEASE",
"org.springframework:spring-orm:4.2.1.RELEASE",
'org.hibernate:hibernate-core:5.0.2.Final',
'mysql:mysql-connector-java:5.1.36'
There is an API project, that contains a User.class. From my opinion this user class must not use any annotations for a database layer. It must not specify #Table(name = "users") or other things. It should be a simple Objects with getters and setters.
The database layer should decide how to store the data and this depends strongly on the database (e.g. MongoDB or MySQL).
I followed some tutorials for Hibernate and ended up with the following #Configuration class
#Configuration
#ComponentScan("de.pentos.proto")
#EnableWebMvc
#EnableTransactionManagement
public class AppConfig {
private static final Logger log = LoggerFactory.getLogger(AppConfig.class);
private static Properties getHibernateProperties() {
final Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
// properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("hbm2ddl.auto", "create");
return properties;
}
{
log.debug("Here am I: {}");
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/myschema");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
#Inject
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(final DataSource dataSource) {
final LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addAnnotatedClasses(User.class);
sessionBuilder.addProperties(getHibernateProperties());
return sessionBuilder.buildSessionFactory();
}
#Inject
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(final SessionFactory sessionFactory) {
final HibernateTransactionManager transactionManager = new HibernateTransactionManager(
sessionFactory);
return transactionManager;
}
}
It works very well, except it uses an annotated class.
How can I add my hbm/user.xml to the sessionBuilder?
I tried with Configuration class, that I found in some examples, but the Method buildSessionFactory() is deprecated.
I also tried the ServiceRegistry described here but then lost my datasource approach and without the datasource the system was not able to setup the HibernateTransactionManager.
Without HibernateTransactionManager I was not able to use #Transactional and I don't like to open and close me transactions manually.
Currently I'm spinning in circles and really need help to get it to work. I already thought about throwing Hibernate away and use my good old MyBatis approach, but you know, I like to learn something new...
Add xml files as a resource to SessionFactory, as follows:
#Inject
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(final DataSource dataSource) {
final LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addResource("/path-to-/hbm/user.xml");
sessionBuilder.addAnnotatedClasses(User.class);
sessionBuilder.addProperties(getHibernateProperties());
return sessionBuilder.buildSessionFactory();
}

how can i parameterize datasource properties on Spring 4?

I am using Spring 4.16. I want to parameterize my persistence data. This is my config right now:
#Configuration
#EnableTransactionManagement
public class PersistenceConfiguration {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setDataSource(this.dataSource());
entityManager.setPackagesToScan(new String[] {"com.example.movies.domain"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManager.setJpaVendorAdapter(vendorAdapter);
entityManager.setJpaProperties(this.properties());
return entityManager;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/sarasa_db");
dataSource.setUsername("root");
dataSource.setPassword("mypassword");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties properties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.show_sql", "false");
return properties;
}
}
And i want to parameterize on my application.properties all things i can. First of all, i want to put in datasource properties (so as i was reading, is possible that spring builds my datasource automatically, but apparently that is only using JdbcTemplate...):
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sarasa_db
spring.datasource.username=root
spring.datasource.password=mypassword
And, if it's possible, all the Properties's properties, which i couldn't find nothing in doc
Do you know how could i do it ?
EDIT
This is my DAO implementation
#Configuration
#Import(PersistenceConfiguration.class)
public class DAOConfiguration {
#PersistenceContext
private EntityManager entityManager;
#Bean
public ClientDAO clientDAO() {
SimpleJpaRepository<Client, String> support = this.getSimpleJpaRepository(Client.class);
return new MySQLClientDAO(support);
}
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Description("Hibernate repository helper")
protected <T> SimpleJpaRepository<T, String> getSimpleJpaRepository(Class<T> domainClass) {
return new SimpleJpaRepository<T, String>(domainClass, this.entityManager);
}
}
You could do something like this:
First define PropertySourcesPlaceholderConfigurer bean somewhere in your Spring configuration:
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setLocation(new ClassPathResource("application.properties"));
return ppc;
}
This configuration assumes that application.properties file is placed at the root of your classpath.
After setting up the property placeholder configurer you can access the properties in your database configuration class like so:
#Configuration
#EnableTransactionManagement
public class PersistenceConfiguration {
#Value("${spring.datasource.url}")
private String jdbcUrl;
// ...
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(jdbcUrl);
// ...
}
}
If you want an easy way to parametrize all properties, you should take a look at Spring Boot. It uses the application.properties file to automatically create data source with those properties, and many other things. This is probably the automatic datasource creation you mentioned in your question.

Categories