I have configured Spring and Hibernate for Mysql but hibernate is not creating tables automatically.i have configured mysql in eclipse datasource connection and tried with tomcat 8 and tomcat 9
I have Configured Database properties to configure hibernate
please find the code below
Database.properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/bookdb
mysql.user=root
mysql.password=root
# Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
#C3P0 properties
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=150
AppConfig
package com.bushansirgur.config;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import static org.hibernate.cfg.Environment.*;
#Configuration
#PropertySource("classpath:db.properties")
#EnableTransactionManagement
#ComponentScans(value = { #ComponentScan("com.bushansirgur.dao"),
#ComponentScan("com.bushansirgur.service") })
public class AppConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
Properties props = new Properties();
// Setting JDBC properties
props.put(DRIVER, env.getProperty("mysql.driver"));
props.put(URL, env.getProperty("mysql.url"));
props.put(USER, env.getProperty("mysql.user"));
props.put(PASS, env.getProperty("mysql.password"));
// Setting Hibernate properties
props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));
// Setting C3P0 properties
props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));
props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));
props.put(C3P0_ACQUIRE_INCREMENT,
env.getProperty("hibernate.c3p0.acquire_increment"));
props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));
props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));
factoryBean.setHibernateProperties(props);
factoryBean.setPackagesToScan("com.bushansirgur.model");
return factoryBean;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
}
MyWebAppIntitalizer
package com.bushansirgur.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
WebConfig
package com.bushansirgur.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.bushansirgur.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {
}
BookModel.java
package com.bushansirgur.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity(name = "Book")
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String author;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
The problem is AppConfig class is in package com.bushansirgur.config which is not under the#ComponentScan, and also i do see multiple #ComponentScan annotations on different class which is not recommended. You can simply use it once on Main class with base package
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.bushansirgur" })
public class WebConfig extends WebMvcConfigurerAdapter {
}
Related
I have gone through available example and tutorials on how to set hibernate.dialect property correctly but found no approach suitable for my situation.
This tutorial is working best for me, but it lacks the ability to set hibernate.dialect property dynamically as I have different types of databases to connect to:
MS SQL
Oracle
H2
MySQL
With incorrect dialect, my JPA (delete/update) queries fail.
With below implementation of #Configuration, which works perfectly, how may I be able to set hibernate.dialect dynamically at runtime for each datasource?
Thank you in advance.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "com.example.multidb",
entityManagerFactoryRef = "multiEntityManager",
transactionManagerRef = "multiTransactionManager"
)
public class PersistenceConfiguration {
private final String PACKAGE_SCAN = "com.example.multidb";
#Primary
#Bean(name = "mainDataSource")
#ConfigurationProperties("app.datasource.main")
public DataSource mainDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
#Bean(name = "clientADataSource")
#ConfigurationProperties("app.datasource.clienta")
public DataSource clientADataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
#Bean(name = "clientBDataSource")
#ConfigurationProperties("app.datasource.clientb")
public DataSource clientBDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
#Bean(name = "multiRoutingDataSource")
public DataSource multiRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.MAIN, mainDataSource());
targetDataSources.put(DBTypeEnum.CLIENT_A, clientADataSource());
targetDataSources.put(DBTypeEnum.CLIENT_B, clientBDataSource());
MultiRoutingDataSource multiRoutingDataSource = new MultiRoutingDataSource();
multiRoutingDataSource.setDefaultTargetDataSource(mainDataSource());
multiRoutingDataSource.setTargetDataSources(targetDataSources);
return multiRoutingDataSource;
}
#Bean(name = "multiEntityManager")
public LocalContainerEntityManagerFactoryBean multiEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(multiRoutingDataSource());
em.setPackagesToScan(PACKAGE_SCAN);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean(name = "multiTransactionManager")
public PlatformTransactionManager multiTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
multiEntityManager().getObject());
return transactionManager;
}
#Primary
#Bean(name = "dbSessionFactory")
public LocalSessionFactoryBean dbSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(multiRoutingDataSource());
sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
//set hibernate.dialect for each datasource
return properties;
}
}
I've created a working example for you, I'll describe it here but if you want to jump in the code yourself it's available at this GitHub repo.
In my case, I've created two data sources, one for User and another one for Item.
Here the entities:
package com.marcosbarbero.so.multiple.ds.entity.user;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Data
#Entity
#Table(schema = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
#Column(unique = true, nullable = false)
private String email;
private int age;
}
package com.marcosbarbero.so.multiple.ds.entity.item;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Data
#Entity
#Table(schema = "item")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
}
Note, It's important to have distinct packages for each domain.
Then I created the Repositories
package com.marcosbarbero.so.multiple.ds.repository.user;
import com.marcosbarbero.so.multiple.ds.entity.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
}
package com.marcosbarbero.so.multiple.ds.repository.item;
import com.marcosbarbero.so.multiple.ds.entity.item.Item;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ItemRepository extends JpaRepository<Item, Integer> {
}
Nothing special about the repos. Let's move to the final piece, the configuration.
I created a #ConfigurationProperties class to externalize my configuration, bear with me, I know the naming is not the best :)
package com.marcosbarbero.so.multiple.ds.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
#Data
#Component
#ConfigurationProperties(prefix = "multi-datasource")
public class MultipleDataSourceProperties {
private UserDataSourceProperties user = new UserDataSourceProperties();
private ItemDataSourceProperties item = new ItemDataSourceProperties();
#Data
public static class UserDataSourceProperties {
private HibernateProperties hibernate = new HibernateProperties();
}
#Data
public static class ItemDataSourceProperties {
private HibernateProperties hibernate = new HibernateProperties();
}
#Data
public static class HibernateProperties {
private Map<String, String> properties = new HashMap<>();
}
}
We'll see the properties configuration file soon.
Now let's create the DataSource for the User:
package com.marcosbarbero.so.multiple.ds.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
#EnableJpaRepositories(
basePackages = "com.marcosbarbero.so.multiple.ds.repository.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager"
)
public class UserDataSourceConfig {
private final MultipleDataSourceProperties properties;
public UserDataSourceConfig(MultipleDataSourceProperties properties) {
this.properties = properties;
}
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean userEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan("com.marcosbarbero.so.multiple.ds.entity.user");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(properties.getUser().getHibernate().getProperties());
return em;
}
#Primary
#Bean
#ConfigurationProperties("multi-datasource.user")
public DataSource userDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
#Primary
#Bean
public PlatformTransactionManager userTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(userEntityManager().getObject());
return transactionManager;
}
}
The important part for you at this class is the line em.setJpaPropertyMap(properties.getUser().getHibernate().getProperties()); it's getting the User's Hibernate configuration properties from our #ConfigurationProperties class defined above.
Now let's do the same for the Item:
package com.marcosbarbero.so.multiple.ds.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
#EnableJpaRepositories(
basePackages = "com.marcosbarbero.so.multiple.ds.repository.item",
entityManagerFactoryRef = "itemEntityManager",
transactionManagerRef = "itemTransactionManager"
)
public class ItemDataSourceConfig {
private final MultipleDataSourceProperties properties;
public ItemDataSourceConfig(MultipleDataSourceProperties properties) {
this.properties = properties;
}
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean itemEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(itemDataSource());
em.setPackagesToScan("com.marcosbarbero.so.multiple.ds.entity.item");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(properties.getItem().getHibernate().getProperties());
return em;
}
#Primary
#Bean
#ConfigurationProperties("multi-datasource.item")
public DataSource itemDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
#Primary
#Bean
public PlatformTransactionManager itemTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(itemEntityManager().getObject());
return transactionManager;
}
}
The application.properties
multi-datasource.item.jdbcUrl=jdbc:h2:mem:spring_jpa_item;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS ITEM
multi-datasource.item.username=sa
multi-datasource.item.password=sa
multi-datasource.item.hibernate.properties.hibernate.hbm2ddl.auto=create-drop
multi-datasource.item.hibernate.properties.hibernate.cache.use_second_level_cache=false
multi-datasource.item.hibernate.properties.hibernate.cache.use_query_cache=false
multi-datasource.item.hibernate.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
multi-datasource.user.jdbcUrl=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USER
multi-datasource.user.username=sa
multi-datasource.user.password=sa
multi-datasource.user.hibernate.properties.hibernate.hbm2ddl.auto=create-drop
multi-datasource.user.hibernate.properties.hibernate.cache.use_second_level_cache=false
multi-datasource.user.hibernate.properties.hibernate.cache.use_query_cache=false
multi-datasource.user.hibernate.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect
Some unit tests
package com.marcosbarbero.so;
import com.marcosbarbero.so.multiple.ds.entity.item.Item;
import com.marcosbarbero.so.multiple.ds.entity.user.User;
import com.marcosbarbero.so.multiple.ds.repository.item.ItemRepository;
import com.marcosbarbero.so.multiple.ds.repository.user.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertNotNull;
#SpringBootTest
public class JPAMultipleDBTest {
#Autowired
private UserRepository userRepository;
#Autowired
private ItemRepository itemRepository;
#Test
public void whenCreatingUser_thenCreated() {
User user = new User();
user.setName("John");
user.setEmail("john#test.com");
user.setAge(20);
user = userRepository.save(user);
assertNotNull(userRepository.findById(user.getId()));
}
#Test
public void whenCreatingProduct_thenCreated() {
Item item = new Item();
item.setName("Book");
item.setId(2);
item = itemRepository.save(item);
assertNotNull(itemRepository.findById(item.getId()));
}
}
I think it also worth mentioning, to make it all work I disabled the DataSourceAutoConfiguration, it's simple as that:
#SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
And again, it all is available at this GitHub repo.
I need some help.
Spring doesn't seem to recognize my methods which was annotated with #Transactional. I watched a lot of sources for solution but couldn't find one.
And I need to annotate exactly dao methods, not services(I know that this is best practice).
P.S. Sorry for my bad english.
My appInitializer:
package com.dreamteam.datavisualizator.common.configurations;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ServletContext.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{ApplicationContext.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
My servletContext:
package com.dreamteam.datavisualizator.common.configurations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#ComponentScan(basePackages = "com.dreamteam.datavisualizator")
#EnableWebMvc
#EnableTransactionManagement
public class ServletContext extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
My applicationContext:
package com.dreamteam.datavisualizator.common.configurations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
#Configuration
public class ApplicationContext {
#Bean(name = "dataSource")
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl(System.getenv("SQL_JDBC_URL"));
dataSource.setUsername(System.getenv("SQL_LOGIN"));
dataSource.setPassword(System.getenv("SQL_PASSWORD"));
return dataSource;
}
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(getDataSource());
}
#Bean(name="generalTemplate")
public JdbcTemplate getJdbcTemplate(){
return new JdbcTemplate(getDataSource());
}
#Bean(name="simpleCallTemplate")
public SimpleJdbcCall getSimpleJdbcCall(){
return new SimpleJdbcCall(getDataSource());
}
}
My Dao class (in this method can be more calls of SimpleJdbcCall/ but that for example):
#Repository("userDaoImpl")
public class UserDAOImpl implements UserDAO {
private enum UserColumnName {ID, FIRST_NAME, LAST_NAME, EMAIL}
#Autowired
private JdbcTemplate generalTemplate;
#Autowired
private SimpleJdbcCall simpleCallTemplate;
//...
#Transactional
public BigInteger createObject(BigInteger object_id, String name) {
simpleCallTemplate.withFunctionName(INSERT_OBJECT);
SqlParameterSource in = new MapSqlParameterSource()
.addValue("obj_type_id", object_id)
.addValue("obj_name", name);
return simpleCallTemplate.executeFunction(BigDecimal.class, in).toBigInteger();
}
//...
private String INSERT_OBJECT = "insert_object";
}
Your configuration seems to be correct. I believe it's not working because you did not specify rollbackFor
#Transactional(value = "transactionManager", rollbackFor = java.lang.Exception.class)
public BigInteger createObject(BigInteger object_id, String name) {
simpleCallTemplate.withFunctionName(INSERT_OBJECT);
SqlParameterSource in = new MapSqlParameterSource()
.addValue("obj_type_id", object_id)
.addValue("obj_name", name);
return simpleCallTemplate.executeFunction(BigDecimal.class, in).toBigInteger();
}
Now if an exception of type java.lang.Exception occurs in your method, it'll rollback all changes
Maybe it is because of Open Session?
https://vladmihalcea.com/the-open-session-in-view-anti-pattern/
Try that in the properties file:
spring.jpa.open-in-view=false
i am a beginner to spring boot and I am performing a CRUD operation on database using spring boot .the program complies with no error but during running my application i encounter an error: NullPointerException.
this is my program:-
CrudOperationApplication.java
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CrudOperationApplication {
public static void main(String[] args) {
SpringApplication.run(CrudOperationApplication.class, args);
}
}
DatabaseCon.java
package com;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#ComponentScan({ "com" })
#Configuration
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class DatabaseCon {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
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 s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
Employee.java
package com;
import javax.persistence.*;
#Entity
#Table(name="Employee")
public class Employee {
#Id
int id;
#Column(name="name")
String name;
#Column(name="salary")
int salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
}
}
EmployeeDao.java
package com;
public interface EmployeeDao {
String insertValue(Employee e);
String updateValue(Employee e);
String deleteValue(Employee e);
String getValue();
String getSpecificValue( int id);
}
EmployeeController.java
package com;
import java.util.*;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class EmployeeController implements EmployeeDao{
HibernateTemplate ht;
Employee e=new Employee();
void setHt(HibernateTemplate ht)
{
this.ht=ht;
}
// for insertion into database
#RequestMapping(value="/",method=RequestMethod.POST)
public String insertValue(Employee e)
{
e.setId(1);
e.setName("james");
e.setSalary(7000);
ht.persist(e);
return "value saved to database";
}
//for updation
#RequestMapping(value="/",method=RequestMethod.PUT)
public String updateValue(Employee e)
{
ht.update(e);
return "value updated to database";
}
//for deletion
#RequestMapping(value="/",method=RequestMethod.DELETE)
public String deleteValue(Employee e)
{
ht.delete(e);
return "value deleted from database";
}
// get stored values from d.b
#RequestMapping(value="/",method=RequestMethod.GET)
public String getValue()
{
List<Employee> al=new ArrayList<Employee>();
al=ht.loadAll(Employee.class);
return ""+al;
}
// to get particular value from d.b
#SuppressWarnings("unchecked")
#RequestMapping(value="/{id}",method=RequestMethod.GET)
public String getSpecificValue(#PathVariable int id)
{
List<Employee> al=new ArrayList<Employee>();
al=(List<Employee>) ht.load(Employee.class,id);
return ""+al;
}
}
Application.properties
jdbc.driverClassName = org.postgresql.Driver
jdbc.url = jdbc:postgresql://localhost:5432/testc
jdbc.db=testc
jdbc.port=5432
jdbc.ip= 127.0.0.1
jdbc.username = postgres
jdbc.password = root
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
You are using Spring Boot then use Spring Boot. Currently you are trying really hard to NOT use Spring Boot.
First instead of you manually configuration a DataSource let Spring Boot do it for you. Remove the #Bean for DataSource and add spring.datasource properties in your application.properties (or simply rename the existing ones).
spring.datasource.url=jdbc:postgresql://localhost:5432/testc
spring.datasource.username=postgres
spring.datasource.password=root
Next instead of using plain Hibernate I strongly suggest to start using JPA instead. So remove the definition for the LocalSessionFactoryBean and HibernateTransactionManager. Simply add the following properties to your configuration.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Now basically have an empty configuration class simply remove it. Spring Boot will already component-scan for you, create JPA, enable transactions.
In your controller/dao hybrid (which is a bad thing imho!) instead of the HibernateTemplate use the EntityManager instead. However I would suggest separating the dao and controller functionality.
#Repository
#Transactional
public class EmployeeDaoJpa implements EmployeeDao {
#PersistenceContext
private EntityManager em;
// Method implementations using the EntityManager
}
Now in your controller use that dao.
#RestController
public class EmployeeController {
private final EmployeeDao dao;
#Autowired
public EmployeeController(EmployeeDao dao) {
this.dao=dao;
}
// for insertion into database
#RequestMapping(value="/",method=RequestMethod.POST)
public String insertValue(Employee e) {
e.setId(1);
e.setName("james");
e.setSalary(7000);
dao.insertvalue(e);
return "value saved to database";
}
//for updation
#RequestMapping(value="/",method=RequestMethod.PUT)
public String updateValue(Employee e) {
dao.updateValue(e);
return "value updated to database";
}
//for deletion
#RequestMapping(value="/",method=RequestMethod.DELETE)
public String deleteValue(Employee e) {
ht.delete(e);
return "value deleted from database";
}
// get stored values from d.b
#RequestMapping(value="/",method=RequestMethod.GET)
public String getValue() {
return ""+dao.findAll();
}
// to get particular value from d.b
#SuppressWarnings("unchecked")
#RequestMapping(value="/{id}",method=RequestMethod.GET)
public String getSpecificValue(#PathVariable int id) {
return ""+dao.findOne(id);
}
}
Another tip don't use com as your package first it is to lowlevel and when Spring or your container starts scanning the com package it will scan everything in the com package. Like everything in jar files starting with com. So invent a better package naming.
In the end you now only have your controller, repository class and interface and finally your application class. No more configuration class that is all nicely in your application.properties.
I am trying to setup a simple test environment for my JUnit, Spring, Hibernate environment. I am also trying to config the whole thing in Java and keep away from XML files for now.
So far, I was able to #Autowire #Beans, but I can't make #Entity available. I keep getting an exception saying my entity wasn't registered.
Here is a sample of what I am doing:
JpaTestConfig.java
package com.springtest.test.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class JpaTestConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
LocalContainerEntityManagerFactoryBean lcemfb
= new LocalContainerEntityManagerFactoryBean();
lcemfb.setDataSource(this.dataSource());
lcemfb.setPackagesToScan(new String[] {"com.jverstry"});
lcemfb.setPersistenceUnitName("MyTestPU");
HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
lcemfb.setJpaVendorAdapter(va);
Properties ps = new Properties();
ps.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
ps.put("hibernate.hbm2ddl.auto", "create");
lcemfb.setJpaProperties(ps);
lcemfb.afterPropertiesSet();
return lcemfb;
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl("jdbc:hsqldb:mem:testdb");
ds.setUsername("sa");
ds.setPassword("");
return ds;
}
#Bean
public PlatformTransactionManager transactionManager(){
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
return tm;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
}
ServiceConfig.java
package com.springtest.test.configuration;
import com.springtest.services.UserService;
import com.springtest.services.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = {
"com.springtest.service"
})
public class ServiceConfig {
#Bean
public UserService getuserService() {
return new UserServiceImpl();
}
}
And my test file. UserServiceTest.java
package com.springtest.test.services;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.springtest.pojo.User;
import com.springtest.services.UserService;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.springtest.test.configuration.*;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={ JpaTestConfig.class,
ServiceConfig.class})
public class UserServiceTest {
#Autowired
private UserService userService;
#Test
public void testCreateAndRetrieve() {
String json = "{\"firstName\": \"John\", \"lastName\": \"Doe\"}";
User user = userService.create(json);
assertEquals("John", user.getFirstName());
}
}
My Service Bean:
package com.springtest.services;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.criteria.CriteriaQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.gson.GsonBuilder;
import com.springtest.pojo.User;
#Service
public class UserServiceImpl implements UserService {
#PersistenceContext(type=PersistenceContextType.EXTENDED)
EntityManager em;
#Transactional
public User create(String json) {
User user = new GsonBuilder().create().fromJson(json, User.class);
em.persist(user);
return user;
}
}
And my Entity class:
package com.springtest.pojo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
private String firstName;
private String lastName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
In a summary, how do I register the entity on my Java class #Configuration file?
Thanks,
The problem was with the package scanner on my JpaTestConfiguration file. More specifically, this line:
lcemfb.setPackagesToScan(new String[] {"com.springtest.pojo"});
is the one that will browse the packages for #Entity annotated classes. Thank you #Rembo for the tip.
I'm working on little Spring MVC CRUD application. Got some strange problems:
configuration class:
package sbk.spring.simplejc.config;
import java.util.Properties;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration //Specifies the class as configuration
#ComponentScan("sbk.spring.simplejc") //Specifies which package to scan
//#Import({DataBaseConfig.class})
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
#EnableWebMvc //Enables to use Spring's annotations in the code
public class WebAppConfig extends WebMvcConfigurerAdapter{
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
application.properties:
#DB properties:
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=Examples
db.username=sa
db.password=
#Hibernate Configuration:
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.show_sql=true
entitymanager.packages.to.scan=sbk.spring.simplejc.entity
#Entity class:
package sbk.spring.simplejc.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="Team")
public class Team {
#Id
#GeneratedValue
private Integer id;
private String name;
private Integer rating;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getRating() {
return rating;
}
public void setRating(Integer rating) {
this.rating = rating;
}
}
Controller class:
package sbk.spring.simplejc.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import sbk.spring.simplejc.service.ITeamService;
#Controller
public class TeamController {
#Autowired
ITeamService service;
#RequestMapping(value="/")
public ModelAndView goToHelloPage() {
ModelAndView view = new ModelAndView();
view.addObject("teamList", service.listTeams());
return view;
}
}
Error stack trace:
org.hibernate.hql.internal.ast.QuerySyntaxException: Team is not mapped [from Team]
org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:180)
org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:110)
org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:93)
org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:324)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3420)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3309)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:706)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:562)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:299)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:247)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:248)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:183)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:105)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:168)
org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:221)
org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:199)
org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1777)
sbk.spring.simplejc.dao.HibTeamDAO.listTeams(HibTeamDAO.java:23)
sbk.spring.simplejc.service.TeamService.listTeams(TeamService.java:27)
I haven't got a clue about this issue.
Update
DAO class:
package sbk.spring.simplejc.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import sbk.spring.simplejc.entity.Team;
#Repository
public class HibTeamDAO implements TeamDAO {
#Autowired
private SessionFactory sessionFactory;
public void addTeam(Team team) {
sessionFactory.getCurrentSession().save(team);
}
public void updateTeam(Team team) {
sessionFactory.getCurrentSession().update(team);
}
#SuppressWarnings("unchecked")
public List<Team> listTeams() {
return sessionFactory.getCurrentSession().createQuery("from Team").list();
}
#SuppressWarnings("unchecked")
public Team getTeamById(Integer teamID) {
Session session = sessionFactory.getCurrentSession();
List<Team> listTeam = session.createQuery("from Team t where t.id = :teamID")
.setParameter("teamID", teamID)
.list();
return listTeam.size() > 0 ? (Team)listTeam.get(0) : null;
}
public void removeTeam(Integer teamID) {
Team team = (Team) sessionFactory.getCurrentSession().load(Team.class, teamID);
if(team != null){
sessionFactory.getCurrentSession().delete(team);
}
}
#Override
public Integer count() {
return (Integer) sessionFactory.getCurrentSession().createQuery("select count(t) from Team t").uniqueResult();
}
}
TeamController class:
package sbk.spring.simplejc.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import sbk.spring.simplejc.service.ITeamService;
#Controller
public class TeamController {
#Autowired
ITeamService service;
#RequestMapping(value="/")
public ModelAndView goToHelloPage() {
ModelAndView view = new ModelAndView();
view.addObject("teamList", service.listTeams());
return view;
}
}
Update
Now I got rid from this problem by changing DAO method from
return sessionFactory.getCurrentSession().createQuery("from Team").list();
to
return sessionFactory.getCurrentSession().createQuery("from sbk.spring.simplejc.entity.Team").list();
But received another issue: every query return null despite of existing rows in Team table.
Update
Finally I noticed warning messages:
Feb 15, 2014 7:01:05 PM org.hibernate.hql.internal.QuerySplitter concreteQueries
WARN: HHH000183: no persistent classes found for query class: from sbk.spring.simplejc.entity.Team
Update
At least I've sorted out this issue by adding next row of code in dataSource bean definition in WebAppConfig:
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setAnnotatedClasses(new Class[]{Team.class});//new row!!!
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
In my case it was because I didn't have the hibernate packagesToScan property. I see that you have it. May be this comment will be useful for someone who missed it.
"No, in this instance I've got org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: * near line 1, column 8 [select * from Team] – Sobik Feb 15 at 10:29"
Instead "Select * from Team" try write "from Team". Because Hibernate works with java entity.