I use JpaRepository to save data, but the hibernate.show_sql shows "select" and won't save data. Following is my service:
#Autowired
private UserRepository userRepository;
#PostConstruct
public void init() {
User admin = new User();
admin.setDisplayName("admin");
admin.setEmailAddress("admin#admin");
admin.setPassword("admin___");
admin.setRegisteredAt(new Date());
admin.setLastAccessAt(new Date());
admin.setUuid(UUID.randomUUID().toString());
try {
System.out.println("before save");
userRepository.save(admin);
System.out.println("after save");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
The output looks like this:
========before save======
Hibernate: select user0_.uuid as uuid1_0_0_, user0_.display_name as display_2_0_0_, user0_.email_address as email_ad3_0_0_, user0_.last_access_at as last_acc4_0_0_, user0_.password as password5_0_0_, user0_.registered_at as register6_0_0_ from User user0_ where user0_.uuid=?
========after save=======
Following is my applicationContext.xml:
<context:component-scan base-package="test">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/helloworld" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="test.entity"></property>
<property name="dataSource" ref="myDataSource" />
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource" />
</bean>
<jpa:repositories base-package="test.repository"
entity-manager-factory-ref="myEmf" transaction-manager-ref="transactionManager"></jpa:repositories>
Attached is my class generated by JPA Tools:
#Entity
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String uuid;
#Column(name="display_name")
private String displayName;
#Column(name="email_address")
private String emailAddress;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="last_access_at")
private Date lastAccessAt;
private String password;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="registered_at")
private Date registeredAt;
public User() {
}
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getDisplayName() {
return this.displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getEmailAddress() {
return this.emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public Date getLastAccessAt() {
return this.lastAccessAt;
}
public void setLastAccessAt(Date lastAccessAt) {
this.lastAccessAt = lastAccessAt;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getRegisteredAt() {
return this.registeredAt;
}
public void setRegisteredAt(Date registeredAt) {
this.registeredAt = registeredAt;
}
}
Since you're using JPA, the transaction manager should be a JpaTransactionManager, not a DataSourceTransactionManager.
Related
I am new to Spring and learning the transaction concepts. Unable to get the #Transactional to work.
Use Case:
Data insert of Employee and Employee details should rollback when getEmployee() throws RunTimeException. But the rollback is not happening.
I am using Oracle database 11g and spring 4.3.1.RELEASE. Below is the standalone java code am running.
Code
public static void main( String[] args )
{
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring-bean.xml");
ctx.registerShutdownHook();
Employee emp = new Employee("149518", "Mickey", "Mouse", "15 years", "tennis");
IEmployee empIntfc = (IEmployee)ctx.getBean("empService");
try {
empIntfc.createEmployee(emp);
empIntfc.createEmployeeDetails(emp);
//Below will throw RunTime Exception
empIntfc.getEmployee(2);
}catch (Exception e ) {
e.printStackTrace();
} finally {
ctx.close();
}
}
EmployeeService.java
public class EmployeeService implements IEmployee {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
jdbcTemplate = new JdbcTemplate(this.dataSource);
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
#Override
#Transactional
public int createEmployee(Employee emp) {
String sql1 = "INSERT INTO TEST_T1(EMP_ID, EMP_FNAME, EMP_LNAME) values
(?,?,?)";
return getJdbcTemplate().update(sql1, emp.getEmpId(),
emp.getEmpFirstName(), emp.getEmpLastName());
}
#Override
#Transactional
public int createEmployeeDetails(Employee emp) {
String sql = "INSERT INTO TEST_T2(EMP_ID, EXP, SKILLS) values (?,?,?)";
return getJdbcTemplate().update(sql, emp.getEmpId(), emp.getExp(),
emp.getSkills());
}
#Override
#Transactional(readOnly = true, noRollbackFor=RuntimeException.class)
public Employee getEmployee(int empId) {
throw new RuntimeException("Intentional runtime exception");
}
}
spring-bean.xml
<beans xmlns="http://www.springframework.org/schema/beans">
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#//xxxx:1521/xxxx"/>
<property name="username" value="user"/>
<property name="password" value="user"/>
</bean>
<bean id="empService" class="com.service.EmployeeService">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Your main method is not transactional ... means : entering 'createEmployee' creates a new transaction and commits it, 'createEmployeeDetails' creates a new transaction and commits it .
This is not a duplicate of this question. So please don't close it for "is duplicate of" reasons..
I am trying to autowire a private field in my service class using this tutorial. My problem is that restaurantOwnerRepository remains null and does not get initialized.
servlet-context.xml
<context:component-scan base-package="com.mahlzeit.web.server" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="restaurantOwnerRepository" class="com.mahlzeit.web.server.dao.RestaurantOwnerRepository">
<constructor-arg>
<ref bean="sessionFactory" />
</constructor-arg>
</bean>
Service code:
#Component
public class RestaurantInformationServiceImpl extends XsrfProtectedServiceServlet implements RestaurantInformationService {
private static final long serialVersionUID = -4088840947018614411L;
#Autowired
private RestaurantOwnerRepository restaurantOwnerRepository;
private final static Logger logger = Logger.getLogger(RestaurantInformationServiceImpl.class);
#Override
public List<RestaurantDTO> getAvailableRestaurants() {
// restaurantOwnerRepository is 'null'
List<Restaurant> availableRestaurants = restaurantOwnerRepository.getAvailableRestaurants(getSessionId());
return null;
}
private String getSessionId() {
HttpServletRequest httpRequest = getThreadLocalRequest();
return httpRequest.getSession().getId();
}
}
RestaurantOwnerRepository.java
public class RestaurantOwnerRepository implements RestauranOwnerDAO {
private SessionFactory sessionFactory;
public RestaurantOwnerRepository(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ..
}
What could be the reason for this?
here is a sample controller for your example , you should define the bean in your context.xml or if you place it in this package : com.mahlzeit.web.server it will be managed by spring automatically , cause as i see you have placed the context:component-scan
#Controller
public class RestaurantInformationServiceImpl {
#Autowired
private RestaurantOwnerRepository restaurantOwnerRepository;
#RequestMapping(value="/")
public #ResponseBody ModelAndView getRestaurants(
HttpServletRequest request,
HttpServletResponse response) {
ModelAndView model = new ModelAndView("yourPage");
List<?> rests = restaurantOwnerRepository.getAvailableRestaurants(httpRequest.getSession().getId());
model.addObject("restList", rests );
return model;
}
}
When I am prining data in console with , it is working.
But when I am trying to write data in output text file, it is not working but there is no error.
Can anyone help me that what is issue here??
Bellow is my coding:-
Java Class:
It should be used during writting in file.
import org.springframework.batch.item.file.transform.FieldExtractor;
import com.poc.customer.vo.Person;
public class PersonFieldSetExtractor implements FieldExtractor<Person> {
#Override
public Object[] extract(Person person) {
return new Object[] { person.getSrcId(), person.getSrcCode(),
person.getFirstName(), person.getLastName(),
person.getPincode(), person.getStreet()};
}
}
Java Class:
This will be used after reading from file and during bean population.
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;
import com.poc.customer.vo.Person;
public class PersonFieldSetMapper implements FieldSetMapper<Person> {
#Override
public Person mapFieldSet(FieldSet fieldSet) throws BindException {
Person person = new Person();
person.setSrcId(fieldSet.readString(0));
person.setSrcCode(fieldSet.readString(1));
person.setFirstName(fieldSet.readString(2));
person.setLastName(fieldSet.readString(3));
person.setPincode(fieldSet.readString(4));
//person.setStreet(fieldSet.readString(5));
return person;
}
}
public class Person implements Serializable, Comparable<Person> {
#Override
public int compareTo(Person arg0) {
return this.firstName.compareTo(arg0.getFirstName());
}
private String srcId;
private String srcCode;
private String firstName;
private String lastName;
private String pincode;
private String street;
public String getSrcId() {
return srcId;
}
public void setSrcId(String srcId) {
this.srcId = srcId;
}
public String getSrcCode() {
return srcCode;
}
public void setSrcCode(String srcCode) {
this.srcCode = srcCode;
}
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;
}
public String getPincode() {
return pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
Spring Configuration:-
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<batch:job id="personJob">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="txtFileItemReader" writer="txtFileItemWriter" commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="txtFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<bean id="txtFileItemReader" class="com.poc.batch.util.FlatFileReader">
<!-- Read a csv file -->
<property name="resource" value="classpath:com/cts/poc/batch/resource/Test_Data.txt" />
<property name="lineMapper" ref="lineMapper" />
</bean>
<bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="fieldSetMapper" ref="fieldSetMapper" />
<property name="lineTokenizer" ref="lineTokenizer" />
</bean>
<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value="|"/>
</bean>
<bean id="fieldSetMapper" class="com.poc.batch.util.PersonFieldSetMapper"/>
<!-- Writer to write output txt file -->
<bean id="txtFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:com/cts/poc/batch/resource/Test_Out_Data.txt" />
<property name="appendAllowed" value="true" />
<property name="lineAggregator" ref="lineAggregator"/>
</bean>
<bean id="lineAggregator" class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="|" />
<property name="fieldExtractor" ref="personFieldSetExtractor" />
</bean>
<bean id="personFieldSetExtractor" class="com.poc.batch.util.PersonFieldSetExtractor"/>
</beans>
I am getting error:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
If I add the below snippet in DataSourceContext.xml, I don't get any error and the application works as expected.
<bean id="userDAO" class="com.my.portal.user.UserDAOImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
I would like my scan packages and register beans without above snippet in DataSourceContext.xml.
How can I achieve this?
Here are my complete code:
Web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
DataSourceContext.xml
<!-- Data Source Setup -->
<bean id="myDS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="maxIdle" value="5"/>
<property name="maxActive" value="10"/>
</bean>
<!-- Hibernate Sessionfactory Bean Definition -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDS"/>
<property name="annotatedClasses">
<list>
<value>com.my.portal.user.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Hibernate Transaction Setup -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
User.java
#Entity
#Table(name="USER")
public class User {
#Id
#Column(name="UserId")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int UserId;
private String FirstName;
private String LastName;
public int getUserId() {
return UserId;
}
public void setUserId(int userId) {
UserId = userId;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
#Override
public String toString(){
return "UserId="+UserId+", FirstName="+FirstName+", LastName="+LastName;
}
}
UserController.java
#Controller
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
private UserService userService;
#Autowired
public UserController(UserService userService){
this.userService = userService;
}
#RequestMapping(value = "/user", method = RequestMethod.GET)
public String user(Locale locale, Model model){
model.addAttribute("getUser",userService.getUser());
return "user";
}
UserDAO.java
#Repository
public interface UserDAO {
public List<User> getUser();
}
UserDAOImpl.java
#Repository
#Transactional
public class UserDAOImpl implements UserDAO {
private static final Logger logger = LoggerFactory.getLogger(UserDAOImpl.class);
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
#SuppressWarnings("unchecked")
#Override
public List<User> getUser() {
List<User> userList = currentSession().createQuery("from User").list();
return userList;
}
}
userService.java
#Service
public interface UserService {
public String getMessage();
}
UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
#Autowired
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public String getMessage(){
return "User Registration Page";
}
#SuppressWarnings("unchecked")
#Override
public List<User> getUser(){
logger.info("getUser()");
return this.userDAO.getUser();
}
}
I am facing a problem, when I tried to insert a data into Database through JPA (#persistanceContex)
Observations
Not getting any errors;
Record is not storing into database (save)
When I tried with listAll() ; it retrieving the data from database
Domain
#Entity
public class Test {
#Id
private int id;
#Column(name="full_name")
private String fullName;
#Column(name="mobile_number")
private int mobileNumber;
.....
}
DAO Class
#Repository("testDAO")
#Transactional
public class TestDAO {
private EntityManager entityManager;
#PersistenceContext(unitName="CRUD_Test_Annotation")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void save(Test test){
entityManager.persist(test);
}
}
Service
#Service("testService")
#Transactional
public class TestService {
private static final Logger logger = LoggerFactory.getLogger(TestService.class);
#Autowired(required=true)
private TestDAO testDAO;
public void save(Test test){
logger.info("TestService::save()");
testDAO.save(test);
}
public void list(){
testDAO.getAll();
}
}
Controller
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(Locale locale, Model model) {
Test test = new Test();
test.setId(xx);
test.setFullName("xxxxx");
test.setMobileNumber(yyyyyy);
testService.save(test);
return "home";
}
application-context.xml
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare a JPA entityManagerFactory-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="CRUD_Test_Annotation" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
First of all, you don't need two transaction boundaries, I suggest you remove #Transactional from your DAO and keep the one in your service.
Start by verifying that spring-transaction has initiated a transaction: Use the debugger and stop the application after the transaction boundary, for instance in your TestService.save-method. If transactions are running, you will see org.springframework.transaction.interceptor.TransactionInterceptor#invoke in the call stack. If you don't see the TransactionInterceptor, then that's your problem. Post your persistence.xml file if transactions are running.