Moving annotated jpa entities between environments - hibernate-annotations

I am using spring-data and jpa project facet in sts to generate entities directly from my database schema. What is the best practice in managing the migration of 'annotated' entities between different environments (dev, staging, prod ..etc) .
given an entity
#Entity
#Table(name="DevEnvironment.dbo.mytable")
public class MyTable implements Serializable {}
How do i migrate (only produce maven artifacts targetted to the particular environment) the above entity to
#Entity
#Table(name="ProdEnvironment.dbo.mytable")
public class MyTable implements Serializable {}
perhaps using spel ?
environment spring-data-jpa, spring3.1.0 , o.s.o.j.v.HibernateJpaVendorAdapter
thanks in advance

Although i have not received a final 'recommended' answer
This works fine for me
<!-- entity manager -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="persistenceUnitName" value="mypu" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.default_schema">${default_schema}</prop>
</props>
</property>
</bean>

Related

Native query executeUpdate seems to commit data in Spring transaction

my usecase is following:
When creating an application user (EntityManager.persist) I also have to create a DB user and grant him privileges (that's why I need hibernate nativeQuery).
I have a Spring #Transactional method which calls my DAO with both calls:
#Transactional
public Integer createCompany(Company company) throws Exception {
companyDao.createReportUser(ReportUser user);
...
}
My DAO method looks like this:
getEm().persist(companyReportsUser);
getEm().createNativeQuery("CREATE USER user1#localhost IDENTIFIED BY :password").setParameter("password", password).executeUpdate();
getEm().createNativeQuery("GRANT SELECT ON appdb.v_company TO user1#localhost").executeUpdate();
//several grants
Now, as soon as the first line with executeUpdate() is executed I can see persisted companyReportsUser in database along with DB user (user1#localhost).
All the nativeQueries are executed and immediately commited one by one. Since they are commited, they cannot be rolled back.
There is no auto-commit parameter set anywhere in my configuration so I assume it is 'false' as found in Hibernate docs.
I've tested #Transactional behavior without native queries and it works as supposed to (transaction is rolled back when I throw an RuntimeException and no data are inserted to database)
When debugging I've seen that persist operation delays execution when it is invoked in a running transaction.
Native query seems to create and execute a PreparedStatement immediately (at least I didn't find a queue of any kind.
I suppose that I might not get the interaction between hibernate native query and Spring transaction, but I've took my time reading Spring and Hibernate docs regarding transactions and native queries and did not found anything that would help me.
Maybe there is a better way to create a database user and grant privileges than native queries (although I didn't find any)
Below is my application config:
applicationContext.xml
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory">
<ref local="entityManagerFactory" />
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="domainPU" />
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.user.name}" />
<property name="password" value="${db.user.password}" />
<property name="validationQuery" value="select 1 as dbcp_connection_test" />
<property name="testOnBorrow" value="true" />
</bean>
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="domainPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.domain.Entity1</class>
....
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.jdbc.batch_size" value="100"></property>
<property name="hibernate.order_inserts" value="true"></property>
<property name="hibernate.order_updates" value="true"></property>
<property name="hibernate.c3p0.min_size" value="5"></property>
<property name="hibernate.c3p0.max_size" value="30"></property>
<property name="hibernate.c3p0.timeout" value="300"></property>
<property name="hibernate.c3p0.max_statements" value="100"></property>
<property name="hibernate.c3p0.idle_test_period" value="${hibernate.c3p0.idle_test_period}"></property>
</properties>
</persistence-unit>
Libraries used:
Hibernate 4.1.6.FINAL
Spring 3.2.2.RELEASE
mysql-connector-java-5.1.21
MySQL 5.5
After digging deeper into how transactions work in MySQL I found an answer:
Problem was in the specific statements inside the native sql query.
From MySQL documentation:
13.3.3 Statements That Cause an Implicit Commit
Data definition language (DDL) statements that define or modify database objects (...CREATE TABLE, DROP DATABASE...)
Statements that implicitly use or modify tables in the mysql database (CREATE USER, DROP USER, and RENAME USER..., GRANT, REVOKE, ...)
...
More details here:
http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html
I've decided to split that action into two parts:
ordinary hibernate statements (inside a transaction),
native query statements
and supply user with a tool/action to reinvoke the second part in case when something goes wrong.
Other solution would be migrating to some other RDBMS that supports transactions around DDL operations.

how to use MethodInvokingBean to customize Json Converter for not losing nano seconds from sql.TimeStamp

There is no error caused by the configuration below. However it is not taken efect in Json converter. I am using MethodInvokingBean instead of MethodInvokingFactoryBean because I read that the second one give me a new instance and I am interested in changing the current instance used by RestTemplate. Anyway, I tried the factory one and it doesn't take effect as well.
Honestly, after some weeks searching for, I am wondering if it is really possible to change the default configuration of MapperObject when it is used by RestTemplate. The default configuration is to ignore the nanoseconds and I am really asking myself how someone else has been using RestTemplate when there is the requirement of nanoseconds. I can fix this by changing from sql.TimeStamp to String but it doesn't seem the best approach. If someone else has faced similiar issue and has been able to use sql.TimeStamp with nanoseconds either by changing Jackson Mapper configuration or other way I will appreciate a lot some tips.
//everything start here
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
_myCllientOfRestService = context.getBean(MyCllientOfRestService.class, request, response);
_myCllientOfRestService.myMethod();
// myCllientOfRestService
Public void myMethod(){
//it is not returning the nano seconds and I am sure the nano seconds is available in rest service return side. MyReturnType object has the sql.TimeStamp variable filled in with nanoseconds in the rest service side but it is lost in client side
_myReturnType = restTemplate.postForObject(urlRestService, myParameters,MyReturnType.class);
}
//applicationContext.xml
<bean id="myCllientOfRestService" class="com.someCompany.mhe.log.handler.MyCllientOfRestService" scope="prototype" lazy-init="true">
<property name="restTemplate" ref="restTemplate2" />
</bean>
<bean id="myMIB"
class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject" ref="jacksonObjectMapper" />
<property name="targetMethod" value="configure" />
<property name="arguments">
<list>
<value type="com.fasterxml.jackson.databind.SerializationFeature">WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS</value>
<value>true</value>
</list>
</property>
</bean>
<bean id="myMIB2"
class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject" ref="jacksonObjectMapper" />
<property name="targetMethod" value="configure" />
<property name="arguments">
<list>
<value type="com.fasterxml.jackson.databind.DeserializationFeature">READ_DATE_TIMESTAMPS_AS_NANOSECONDS</value>
<value>true</value>
</list>
</property>
</bean>
<bean id="restTemplate2" class="org.springframework.web.client.RestTemplate" >
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>

Need to avoid using “in PersistenceUnit” while querying on entitymanager

I am using jpa and spring, and got an error with below code;
#PersistenceContext protected EntityManager entityManager;
entityManager.createQuery("select c from Theatre c");
And take this error.
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Theatre is
not mapped [select c from Theatre c]
In order to solve the problem i use below, but i need any other solution because the project should not know the class and i want to make dynamic programming
<class>Theatre </class> in "PersistenceUnit"
I appreciate any idea
Best Regards
You can use the attribute packagesToScan in your LocalContainerEntityManagerFactoryBean definition (available in Spring 3.1). If you use this approach you don't need to define the persistence.xml anymore. The configuration should be something like this:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.sergialmar.domain" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>

Spring 3 with json and xstream output not working

I have this working now now, but am lost as to why this problem occurred..
I followed the following
http://pfelitti87.blogspot.co.uk/2012/07/rest-services-with-spring-3-xml-json.html
but i changed the controller method and added #ResponseBody...
#ResponseBody
#ResponseStatus(HttpStatus.OK)
#RequestMapping(value="/names", method=RequestMethod.GET)
public List<Book> getNames() {
return returnData();
}
By adding this i noticed that the output would appear as json, regardless of the extension i specified?...
Any ideas why #RepsonseBody would cause this issue?
The post only works for resolving different views based on different types. It does not work on your case.
If you are using Spring 3.2.x, the configuration below would solve your problem.
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
<property name="defaultContentType" value="application/json"/>
</bean>
However, if you are using 3.1.x, there are approaches like http://tedyoung.me/2011/07/28/spring-mvc-responsebody and http://springinpractice.com/2012/02/22/supporting-xml-and-json-web-service-endpoints-in-spring-3-1-using-responsebody that might help you.

MessageConverter not being called

I have a custom MessageConverter registered in spring with the following configuration:
<bean id="jsonHttpMessageConverter" class="com.eventwiz.web.util.ServiceResponseHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="jsonHttpMessageConverter"/>
</util:list>
</property>
</bean>
However, it's not being called as I confirmed that with a breakpoint in my code. ServiceResponseHttpMessageConverter subclasses MappingJacksonHttpMessageConverter and overrides writeInternal() method. I've even tried overriding MessageConverter.supports() just to see if that was being called and it wasn't. Any ideas what's going on?
The issue, as was found based on an answer from the author was the <mvc:annotation-driven/> tag which registers its own handlerAdapter, so if another handlerAdapter is added to the Spring MVC configuration file with converters added to this adapter, the custom adapters will not take effect. The fix is to either register the httpMessageConverters through <mvc:message-converters... tag under <mvc:annotation-driven or removing <mvc:annotation-driven and having the custom handleradapter with the httpmessageconverter registered under it.