How do I configure Hibernate Console in Intellij with java config? - java

I have a Persistence configured in Java. No persistence.xml. Intellij shows me the entityManagerFactory and the entities in the Persistence window. The query runs OK in the application.
How do I get the hibernate console in Intellij to run queries?
I get
[2016-09-12 14:09:07] java.lang.NoSuchMethodError: org.hibernate.Session.createQuery(Ljava/lang/String;)Lorg/hibernate/Query
The dialect is hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
The configuration is:
#Configuration
#EnableTransactionManagement
#PropertySource({ "file:${view.config}" })
#ComponentScan({ "my.me.model" })
public class PersistenceConfig {
private static Logger logger = LoggerFactory.getLogger(PersistenceConfig.class);
#Autowired
private Environment env;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("my.me.model");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean
#Autowired
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
#SuppressWarnings("serial")
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers", "true");
setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
}
};
}

This now works in 2106.3 EAP. The answer is to upgrade.

Related

Unable to solve error "save is not valid without active transaction"

I'm unable to solve error
save is not valid without active transaction
my code:
public class PersistenceJPAConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "self.experiment.dto" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
return hemf.getSessionFactory();
}
#Bean
public EntityManager entityManager(){
return entityManagerFactory().getObject().createEntityManager();
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
hibernateTransactionManager.setSessionFactory(sessionFactory);
return hibernateTransactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.setProperty("hibernate.current_session_context_class", "thread");
properties.setProperty("hibernate.show_sql", "false");
return properties;
}
}
public class UserBL {
#Autowired
UserDAO userDao;
#Transactional(transactionManager="transactionManager")
public void saveUsers(){
User user = new User();
user.setName("Bob");
userDao.insert(user);
}
}
On a lot of blogs i have read that removing hibernate.current_session_context_class from JPA property will fix this problem. But when i remove it i get following error
No CurrentSessionContext configured!
You are configuring a SessionFactory and an EntityManagerFactory. Remove all the Hibernate specific stuff:
#Configuration
public class PersistenceJPAConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "self.experiment.dto" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.setProperty("hibernate.show_sql", "false");
return properties;
}
}
Service
public class UserBL {
#Autowired
UserDAO userDao;
#Transactional
public void saveUsers(){
User user = new User();
user.setName("Bob");
userDao.insert(user);
}
}
DAO
public class UserDAO {
#PersistenceContext
private EntityManager em;
}

How to ensure Spring Data JPA does not do DDLs (without Spring-Boot)?

I have the following database config
#Configuration
#EnableJpaRepositories("com.mycompany.databaseutilities.repo")
#ImportResource("classpath:data_source.xml")
public class DataConfig {
#Autowired
DataSource dataSource;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean ans =
new LocalContainerEntityManagerFactoryBean();
ans.setDataSource(dataSource);
ans.setJpaVendorAdapter(jpaVendorAdapter());
ans.setPackagesToScan("com.mycompany.databaseutilities.model");
return ans;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter ans = new HibernateJpaVendorAdapter();
ans.setShowSql(false);
ans.setGenerateDdl(false); // is this sufficient?
ans.setDatabase(Database.MYSQL);
return ans;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager ans = new JpaTransactionManager();
ans.setEntityManagerFactory(entityManagerFactory().getObject());
return ans;
}
}
Package com.mycompany.databaseutilities.model contains classes, annotated by #Entity
Can I be sure, that it won't execute any DDL statements? I don't wish to damage existing database.
You can either specify the spring.jpa.hibernate.ddl-auto property in your spring boot application.properties or application.yaml file.
You can also specify this at the time of creating your LocalContainerEntityManagerFactoryBean by supplying properties:
final Properties jpaProperties = new Properties();
jpaProperties.put( AvailableSettings.HBM2DDL_AUTO, "false" );
entityManagerFactoryBean.setJpaProperties( jpaProperties );

Using <context:component-scan base-package /> in annotation based configuration

I have gone through different resources but still I am not getting my work done. Here is my Spring annotation based configuration :-
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence-mysql.properties" })
#ComponentScan({ "org.baeldung.persistence" })
public class PersistenceJPAConfig {
#Autowired
private Environment env;
public PersistenceJPAConfig() {
super();
}
// beans
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers",
// "true");
return hibernateProperties;
}
}
I have my controller class in org.baeldung.persistence.controller package and denoted #Controller at the top of the class. Still I am getting 404 error when I access the URL /products. Here is my controller class
#Controller
public class ProductViewController {
#RequestMapping(value = "/products", method = RequestMethod.POST)
public String create(#ModelAttribute("product") final Product product) {
final ProductServiceImpl productServiceImpl = new ProductServiceImpl();
if (productServiceImpl.create(product)) {
return "Product with product name : " + product.getProduct_name() + "Has been created";
} else {
return "Error while creating the product record";
}
}
Sinnce your controller class is in org.baeldung.persistence.controller package, you have to scan components in this package
#ComponentScan({ "org.baeldung.persistence.controller" })
you will also need to add #EnableWebMvc in PersistenceJPAConfig class
#EnableWebMvc

Run SpringLiquibase BEFORE Hibernate

I'm using SpringLiquibase to apply my liquibase update automatically during the application startup. In general this works fine, but when I set hibernate.hbm2ddl.auto to "validate" then hibernate starts to complain about the database scheme before liquibase seems to have the chance to apply the updates.
My configuration looks like this:
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "com.myapp")
#PropertySource(value = {"classpath:myapp.properties"})
#EnableJpaRepositories("com.myapp")
public class MyappConfig {
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty("jdbc.driver"));
dataSource.setUrl(env.getRequiredProperty("jdbc.url"));
dataSource.setUsername(env.getRequiredProperty("jdbc.username"));
dataSource.setPassword(env.getRequiredProperty("jdbc.password"));
return dataSource;
}
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource());
liquibase.setChangeLog("classpath:liquibase/liquibase-master-changelog.xml");
return liquibase;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan("com.myapp");
entityManagerFactoryBean.setJpaProperties(hibernateProperties());
return entityManagerFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
String[] propertyNames = new String[]{"hibernate.dialect", "hibernate.show_sql", "hibernate.hbm2ddl.auto"};
for (String propertyName : propertyNames) {
properties.put(propertyName, env.getRequiredProperty(propertyName));
}
return properties;
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
Is there any way to get liquibase to apply its updates BEFORE hibernate tries to validate the schema?
Thanks to M. Deinum I was able to solve this by using
#Bean
#DependsOn("liquibase")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
[...]
}
The #DependsOn makes sure that liquibase is run before Hibernates schema validation.

working with two transactions, one seem to work but the other does not. why?

I'm working with two transactions on spring which has reference to two entitymanagers and hence two datasources, while using #Transactional("transaction1") it works fine but #Transactional("transaction2") throws out an error saying no active transactions found. following is the piece of code:
#Bean(name = "transaction1")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean2()
.getObject());
return transactionManager;
}
#Bean(name = "transaction2")
public PlatformTransactionManager sermaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager
.setEntityManagerFactory(entityManagerFactoryBean1()
.getObject());
return transactionManager;
}
respective entitymanagers:
#Bean(name = "entitymanager1")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean1() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource1());
entityManagerFactoryBean
.setPackagesToScan(new String[] { this.environment
.getProperty("db.packagesToScan") });
entityManagerFactoryBean
.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.level", "INFO");
jpaProperties.put("eclipselink.logging.parameters", "true");
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
#Bean(name = "entitymanager2")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean2() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource2());
entityManagerFactoryBean
.setPackagesToScan(new String[] { this.environment
.getProperty("db.packagesToScan") });
entityManagerFactoryBean
.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.parameters", "true");
jpaProperties.put("eclipselink.logging.level", "INFO");
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
respective datasources:
#Bean("datasource1")
public DriverManagerDataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource .setDriverClassName(this.environment.getProperty("db.driver"));
dataSource.setUrl(this.environment.getProperty("db.url"));
dataSource.setUsername(this.environment
.getProperty("db.username.abc"));
dataSource.setPassword(this.environment
.getProperty("db.password.abc"));
return dataSource;
}
#Bean("datasource2")
public DriverManagerDataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(this.environment.getProperty("db.driver"));
dataSource.setUrl(this.environment.getProperty("db.url"));
dataSource.setUsername(this.environment.getProperty("db.username"));
dataSource.setPassword(this.environment.getProperty("db.password"));
return dataSource;
}
My genericDaoImpl has the following to link respective entitymanagers:
#PersistenceContext(unitName = "entitymanager1")
private EntityManager em1;
#PersistenceContext(unitName = "entitymanager2")
private EntityManager em2;
when i do #Transactional("transaction1") it works fine, but when i do #Transactional("transaction2") it says no active transactions. and when i dont mention the qualifier for the transactions, error says two transactions found (transaction1, transaction2). any help would be great.
There is an issue with the config:
The problem is that when the beans are initialized like this:
transactionManager.setEntityManagerFactory(entityManagerFactoryBean2().getObject());
The call to entityManagerFactoryBean2() will create a new entity manager factory, and then the #Bean annotation will trigger the creation of another entity manager factory, with the same config.
When you inject the entity manager factory with #Autowiredin a bean, you are injecting the instance created with #Bean, and not the instance passed to the transaction manager.
One warning concerning the config:
The config above allows to do transactions in two separate datasources, but it's not possible with this config to do transactions that span the two databases. For example:
#Service
public class PlanesService {
#PersistenceContext(unitName = "entityManagerFactory1")
private EntityManager em1;
#PersistenceContext(unitName = "entityManagerFactory2")
private EntityManager em2;
#Transactional("transactionManager1")
public Plane savePlanes() {
F14 f14 = new F14("F14","f14");
F16 f16 = new F16("F16","f16");
em1.persist(f14);
em2.persist(f16);
return f14;
}
}
This code will only persist f14, because the only entity manager that has an ongoing transaction is em1 (due to #Transactional("transactionManager1")). The call to em2.persist() will be ignored (em2 can still do reads though).
If you want to do transactions that include both databases you need a JTA transaction manager.
An example of a working config:
This an example of a configuration that fixes the above injection issues:
#Configuration
public class DataSourcesConfig {
#Bean(name = "datasource1")
public DriverManagerDataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
return dataSource;
}
#Bean(name = "datasource2")
public DriverManagerDataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
return dataSource;
}
}
#Configuration
public class EntityManagerFactoriesConfiguration {
#Autowired
#Qualifier("datasource1")
private DataSource dataSource1;
#Autowired
#Qualifier("datasource2")
private DataSource dataSource2;
#Bean(name = "entityManagerFactory1")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource1);
entityManagerFactoryBean.setPackagesToScan(new String[] { "your.package.here" });
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
...
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
#Bean(name = "entityManagerFactory2")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean2() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource2);
entityManagerFactoryBean.setPackagesToScan(new String[] { "your.package.here" });
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
...
return entityManagerFactoryBean;
}
}
#Configuration
#EnableTransactionManagement
public class TransactionManagersConfig {
#Autowired
#Qualifier("entityManagerFactory1")
EntityManagerFactory entityManagerFactory1;
#Autowired
#Qualifier("entityManagerFactory2")
EntityManagerFactory entityManagerFactory2;
#Autowired
#Qualifier("datasource1")
private DataSource dataSource1;
#Autowired
#Qualifier("datasource2")
private DataSource dataSource2;
#Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory1);
transactionManager.setDataSource(dataSource1);
return transactionManager;
}
#Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory2);
transactionManager.setDataSource(dataSource2);
return transactionManager;
}
}
By splitting the config in several #Configuration classes and autowiring them, we ensure that it's always the same beans being used (singletons).
Notice the #EnableTransactionManagement annotation, that enables #Transactional.

Categories

Resources