Mapping hibernate table entities through java configuration - spring

How do we map hibernate table resources when we are configuring through java instead of xml config files - appreciate help.
xml-mapping for hibernate resource:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SybaseDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>/config/Stock.hbm.xml</value>
</list>
</property>
</bean>
Java-mapping?
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence-sql.properties" })
#ComponentScan({......."})
public class PersistenceConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] {...... });
sessionFactory.setHibernateProperties(hibernateProperties());
(HOW DO WE INTRODUCE mappingResources HERE?)
return sessionFactory;
}

The #Entity on the model object solved the problem.
The xml configuration option had not needed this annotation.

you can edit your configuration at runtime like this:
Configuration cfg = new Configuration()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");
or for class like this:
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class);
reference here

Here is the minimal working Hibernate+JPA setup you are interested in:
#Configuration
#EnableTransactionManagement
public class DaoConfiguration {
#Bean
public Properties hibernateProperties() {
Properties properties = new Properties();
properties.setProperty(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect");
properties.setProperty(Environment.DRIVER, "org.hsqldb.jdbcDriver");
properties.setProperty(Environment.URL, "jdbc:hsqldb:mem:testdb");
properties.setProperty(Environment.USER, "sa");
properties.setProperty(Environment.PASS, "");
properties.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, "org.springframework.orm.hibernate4.SpringSessionContext");
properties.setProperty(Environment.STATEMENT_BATCH_SIZE, "30");
properties.setProperty(Environment.SHOW_SQL, "true");
properties.setProperty(Environment.HBM2DDL_AUTO, "update");
return properties;
}
#Bean
public HibernateEntityManagerFactory entityManagerFactory() {
Ejb3Configuration config = new Ejb3Configuration();
return (HibernateEntityManagerFactory) config.addProperties(hibernateProperties()).
addAnnotatedClass(User.class).
buildEntityManagerFactory();
}
#Bean
public SessionFactory sessionFactory() {
return entityManagerFactory().getSessionFactory();
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}

Related

Bean Required for Spring MVC xml file for Amazon S3

What should be the beans in xml file for this same java based configuration?
#Configuration
#ComponentScan(basePackageClasses = Application.class, excludeFilters = #Filter({Controller.class, Configuration.class}))
public class ApplicationConfig {
#Value("${aws_access_key_id}")
private String awsId;
#Value("${aws_secret_access_key}")
private String awsKey;
#Bean
public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocations(new Resource[] {
new ClassPathResource("/amazon.properties")
});
return ppc;
}
#Bean
public AWSCredentials credential() {
return new BasicAWSCredentials(awsId, awsKey);
}
#Bean
public AmazonS3 s3client() {
return new AmazonS3Client(credential());
}
}
<context:property-placeholder
ignore-resource-not-found="true" ignore-unresolvable="true"
system-properties-mode="OVERRIDE" order="0"
location="classpath:amazon.properties"/>
<bean id="credential" class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value="${aws_access_key_id}"/>
<constructor-arg name="secretKey" value="${aws_secret_access_key}"/>
</bean>
<bean id="s3client" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg ref="credential"/>
</bean>

JPA, spring-boot, configuring entity Manager with old not annotated classes

I have a brand-new Spring-Boot project using the most recent technologies, just one configuration file application.yml, otherwise I configured all via annotations.
I just have a dependency to some old not annotated entity classes, and when I start the project it crashes because of:
Caused by: org.hibernate.boot.MappingException: Association [old.entity1.SomeOldEntity] references an unmapped entity [old.entity1.SomeOldEntity] : origin(old/entity1/SomeOldEntity.xml)
This is the JPA configuration class:
#Configuration
#EnableJpaRepositories(basePackages = "actual.repositories", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
#EnableTransactionManagement
public class JpaConfiguration {
#Autowired
private Environment environment;
#Value("${my.maxPoolSize:10}")
private int maxPoolSize;
/*
* Populate SpringBoot DataSourceProperties object directly from application.yml based on prefix.Thanks to .yml, Hierachical data is mapped out of the box
* with matching-name properties of DataSourceProperties object].
*/
#Bean
#Primary
#ConfigurationProperties(prefix = "datasource.myApp")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
/*
* Configure HikariCP pooled DataSource.
*/
#Bean
public DataSource dataSource() {
DataSourceProperties dataSourceProperties = dataSourceProperties();
HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder.create(dataSourceProperties.getClassLoader())
.driverClassName(dataSourceProperties.getDriverClassName()).url(dataSourceProperties.getUrl()).username(dataSourceProperties.getUsername())
.password(dataSourceProperties.getPassword()).type(HikariDataSource.class).build();
dataSource.setMaximumPoolSize(maxPoolSize);
return dataSource;
}
/*
* Entity Manager Factory setup.
*/
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(
new String[] { "some.new.model", "old.entity1", "old.entity2" });
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
factoryBean.setJpaProperties(jpaProperties());
return factoryBean;
}
/*
* Provider specific adapter.
*/
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
return hibernateJpaVendorAdapter;
}
/*
* Here you can specify any provider specific properties.
*/
private Properties jpaProperties() {
Properties properties = new Properties();
// Datasource option
String dialect = environment.getRequiredProperty("my.dialect");
String method = environment.getRequiredProperty("my.method");
String show_sql = environment.getRequiredProperty("my.show_sql");
String format_sql = environment.getRequiredProperty("my.format_sql");
String defaultSchema = environment.getRequiredProperty("my.schema");
// Set options
properties.put("hibernate.dialect", dialect);
properties.put("hibernate.hbm2ddl.auto", method);
properties.put("hibernate.show_sql", show_sql);
properties.put("hibernate.format_sql", format_sql);
if (StringUtils.isNotEmpty(defaultSchema)) {
properties.put("hibernate.default_schema", defaultSchema);
}
return properties;
}
#Bean
#Autowired
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(emf);
return txManager;
}
}
EDIT 22.06
here the xml mapping SomeOldEntity:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="old.entity1">
<class name="SomeOldEntity" table="entity1" lazy="false">
<id name="id" column="ID" type="long" access="field">
<generator class="assigned" />
</id>
<property name="moreId" column="MORE_ID" type="long" access="field" />
<property name="aPrefix" column="A_PREFIX" type="java.lang.String" access="field" />
<property name="aKey" column="A_KEY" type="java.lang.String" access="field" />
<property name="active" column="IS_ACTIVE" type="boolean" access="field" />
<one-to-one name="SomeMoreEntity" access="field" fetch="join" />
<one-to-one name="another1OldEntity" property-ref="someOtherId" access="field" fetch="join" />
<one-to-one name="another2OldEntity" property-ref="someOtherId" access="field" fetch="join" />
<one-to-one name="another3OldEntity" property-ref="someOtherId" access="field" fetch="join" />
<list name="impressumList" access="field" lazy="true" fetch="select">
<key column="FK_SOMEID" not-null="true" />
<list-index column="INDEX_ORDER" />
<one-to-many class="some.other.entity.outside.package.SomeEntity" />
</list>
</class>
</hibernate-mapping>
Ok, I think I found the solution, old not Annotated classes has always a xml mapping the class to database entities, well than if I pass the xml like this:
// Old Not Annotated class must be passed as xml to MappingResource
String Entity1 = " old.Entity1.xml";
factoryBean.setMappingResources(Entity1);
Instead of this:
// Annotated classes can be passed as entities throught setPackagesToScan
String Entity1 = "old.Entity1";
factoryBean.setPackagesToScan(new String[] { Entity1 });
IT WORKS!!!

Hibernate using fully JavaConfig aproach in a Spring Batch Job

I have a batch job fully configured using JavaConfig. having difficulties, mainly due to little material I found on configuration using only java. In the spring batch manual itself there is no information on how to fully configure a job with spring batch using only java. I do not know if it's because this configuration model is more recent than the xml based aprouch...
Right now I'm having trouble setting up hibernate using this configuration class. I have an xml settings, but I'm not knowing how to reference it or how to change these settings for a fully "JavaConfig" version.
My job configuration class is:
#Configuration
#EnableBatchProcessing
public class CrawlerBatchConfiguration {
#Autowired
private StepBuilderFactory steps;
#Bean
public Job job(JobBuilderFactory jobs) {
return jobs.get("myJob").start(flow()).end().build();
}
protected Step step0() {
return steps.get("setupCrawlerStep").tasklet(tasklet()).build();
}
private Flow flow() {
FlowBuilder<Flow> builder = new FlowBuilder<>("flow1");
builder.start(step0())
.next(step1())
.end();
return builder.build();
}
#Bean
protected Step step1() {
return steps.get("processProductStep")
.<TransferObject, Product>chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
#Bean
protected Tasklet tasklet() {
return new StartCrawlerTasklet();
}
#Bean
protected ProductList getProductList() {
return new ProductList();
}
#Bean
public CrawlerListener listener() {
CrawlerListener listener = new RibeiraoListener();
return listener;
}
#Bean
public ItemProcessor<TransferObject, Product> processor() {
return new ProductProcessor();
}
#Bean
public ItemReader<TransferObject> reader() {
return new ProductItemReader();
}
#Bean
public ItemWriter<Product> writer() {
return new HIbernateProductsItemWriter();
}
#Bean
public Crawler crawler() {
return new RibeiraoCrawler(new UserAgentFactory());
}
#Bean
public ProductBo productBo() {
return new ProductBoImpl();
}
#Bean
public ProductDao productDao() {
return new ProductDaoImpl();
}
}
And the hibernate config file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hbm2ddl.auto">update</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>br.com.alexpfx.supermarket.domain.Product</value>
<value>br.com.alexpfx.supermarket.domain.Manufacturer</value>
</list>
</property>
</bean>
</beans>

Convert JMS out bound channel adapter to equavalent Spring Integration DSL in java 1.7

How can I convert <int-jms:outbound-channel-adapter channel="topicChannel" destination="requestQueue"/> to equivalent Spring Integration DSL in java 1.7
Below is the ActiveMQ configuration:
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
</property>
<property name="sessionCacheSize" value="10"/>
</bean>
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue.demo"/>
</bean>
#Bean
public ActiveMQQueue requestQueue() {
return new ActiveMQQueue("queue.demo");
}
etc.
You can configure the sender like this:
#Configuration
#ComponentScan(basePackages = { "com.sample.dispatcher" })
public class DispatcherConfig {
public static final String JOB_TOPIC = "jobTopic";
#Bean
#ServiceActivator(inputChannel = JOB_TOPIC)
public MessageHandler outboundJmsAdapter(JmsTemplate template) {
JmsSendingMessageHandler handler = new JmsSendingMessageHandler(template);
handler.setDestinationName(JOB_TOPIC);
return handler;
}
#Bean(name = JOB_TOPIC)
public MessageChannel jobTopic() {
return new PublishSubscribeChannel();
}
}
and the listener like this
#Configuration
#ComponentScan(basePackages = { "com.sample.processor" })
#IntegrationComponentScan(basePackages = { "com.sample.processor" })
public class ProcessorConfig {
public static final String ON_POST_JOB = "onPostJob";
public static final String JOB_TOPIC = "jobTopic";
#Bean
public Queue jobTopic() {
return new ActiveMQQueue(JOB_TOPIC);
}
#Bean
public JmsMessageDrivenEndpoint inboundJmsAdapter(ConnectionFactory connectionFactory) {
return new JmsMessageEndpointBuilder()
.setConnectionFactory(connectionFactory)
.setDestination(JOB_TOPIC)
.setInputChannel(onPostJob())
.build();
}
#Bean(name = ON_POST_JOB)
public MessageChannel onPostJob() {
return new PublishSubscribeChannel();
}
}
I have a sample project that uses jms and Spring Integration as form of communication between two applications running on separate vm/process/:
https://github.com/vineey/sample-jobqueue

Hibernate SessionFactory vs Spring LocalSessionFactoryBean

I am trying to move a spring3.2.x + hibernate4.x setup from a xml to java configuration.
Heres a snippet of the existing code:
import org.hibernate.SessionFactory;
import org.hibernate.Query;
import org.hibernate.Session;
public class StockDaoImpl implements StockDao{
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Stock stock){
Session session = getSessionFactory().openSession();
try{
session.save(stock);
}
finally{
session.close();
}
}
The spring config file
<!-- Stock Data Access Object -->
<bean id="stockDao" class="com.data.dao.StockDaoImpl" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="dataSource">
.....
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
......
</property>
<property name="mappingResources">
.......
</property>
</bean>
This works fine - but how do i re-define this config in java?
Heres an attempt -
#Bean
public StockDao stockDao() {
StockDaoImpl dao=new StockDaoImpl();
dao.setSessionFactory(sessionFactory());
return dao;
}
......
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { .....});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
But this wont compile as the sessionFactory being referred to is not Spring's LocalSessionFactoryBean?
How do I reconcile this?
LocalSessionFactoryBean is a FactoryBean<SessionFactory>. It means that it allows creating instances of SessionFactory.
So you just need
public StockDao stockDao() {
StockDaoImpl dao=new StockDaoImpl();
dao.setSessionFactory(sessionFactory().getObject());
return dao;
}
But I wouldn't create DAOs explicitel like that. Simply annotate your DAO with #Repository, and autowire the session factory using #Autowired. Make sure the Java config class is annotated with #ComponentScan("the.base.package.of.daos")
Missing getObject() call in return.
Substituite with return sessionFactory.getObject() (and change return type,too!)
JB Nizet's answer helped me, but I needed to declare the beans separately for it to work:
#Bean
public LocalSessionFactoryBean sessionFactoryBean(final DataSource dataSource,
final Properties hibernateProperties,
final List<String> hibernateMappings) {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
sessionFactoryBean.setMappingResources(hibernateMappings.toArray(new String[hibernateMappings.size()]));
return sessionFactoryBean;
}
#Bean
public SessionFactory sessionFactory(LocalSessionFactoryBean sessionFactoryBean) {
return sessionFactoryBean.getObject();
}

Resources