Posted In: Spring, Spring Data

Spring Boot + Spring Data JPA + MySQL + Tomcat – Complexity2

In this example we will see how to insert/update data using JPA and impacts of @Transactional

Technologies used

1. Spring Boot 1.5.6

2. Spring data commons 1.13.6

3. Spring data jpa 1.11.6

4. MySQL connector 5.1.43

5. Tomcat JDBC 8.5.16

Steps

1. Create Spring Boot starter project

2. Verify maven pom.xml to have spring-boot-starter, spring-boot-starter-data-jpa, mysql-connector-java, spring-boot-starter-test

3. Add application properties

4. Map the POJO properties with Database table columns

5. Implement CrudRepository interface

6. Test User Repository without and with @Transactional

1a. Create Spring Boot starter project

1b. Create MySQL table

CREATE TABLE user_master (
  USER_ID int(10) NOT NULL AUTO_INCREMENT,
  USER_LOGIN_ID varchar(20) DEFAULT NULL,
  USER_PASSWORD varchar(50) DEFAULT NULL,
  FIRST_NM varchar(50) DEFAULT NULL,
  LAST_NM varchar(50) DEFAULT NULL,
  DT_OF_BIRTH date DEFAULT NULL,
  EMAIL_ID varchar(50) DEFAULT NULL,
  PRIMARY KEY (USER_ID)
)

2. Verify maven pom.xml

<dependencies>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>
</dependencies>

3. Add application properties

spring.datasource.url=jdbc:mysql://localhost:3306/javausecase_db
spring.datasource.username=root
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true

4. Map the POJO properties with Database table columns

@Entity – A JPA entity class is a POJO (Plain Old Java Object) class, i.e. an ordinary Java class that is marked (annotated) as having the ability to represent objects in the database.

@Table – Database table name

@Id – Primary key column

@GeneratedValue – The annotation is to configure the way of increment of the specified column

@Column- Database column name

package com.example.springapp;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "user_master")
public class User implements Serializable {
	private static final long serialVersionUID = 65007985219089594L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long userId;
	@Column(name = "USER_LOGIN_ID")
	private String userLoginId;
	@Column(name = "USER_PASSWORD")
	private String userPassword;
	@Column(name = "FIRST_NM")
	private String firstName;
	@Column(name = "LAST_NM")
	private String lastName;
	@Column(name = "DT_OF_BIRTH")
	private Date dateofBirth;
	@Column(name = "EMAIL_ID")
	private String emailId;
        
        //GETTERS AND SETTERS .....
}

5. Implement CrudRepository interface. We will use save method from CrudRepository to insert data

package com.example.springapp;

import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

public interface UserRepository extends CrudRepository<User, Long> {
}

6a. Test User Repository without @Transactional

@Test
public void testUserRepository() throws Exception {
	LOGGER.debug("Running testUserRepository()....");

	User newUser = new User();
	newUser.setUserId(System.currentTimeMillis());
	newUser.setFirstName("TestFirstName1");
	newUser.setLastName("TestLastName1");
	newUser.setDateofBirth(new SimpleDateFormat("yyyy-MM-dd").parse("1976-01-09"));
	newUser.setEmailId("test@test.com");
	newUser.setUserLoginId("testlogin");
	newUser.setUserPassword("password");

	userRepository.save(newUser);
}

Above save call will save the data to the database

6b. Test User Repository without @Transactional and error condition

@Test
public void testWihOutTransaction2() throws Exception {
	LOGGER.debug("Running testWihOutTransaction2()....");

	User newUser = new User();
	newUser.setUserId(System.currentTimeMillis());
	newUser.setFirstName("TestFirstName3");
	newUser.setLastName("TestLastName3");
	newUser.setDateofBirth(new SimpleDateFormat("yyyy-MM-dd").parse("1976-01-09"));
	newUser.setEmailId("test@test.com");
	newUser.setUserLoginId("testlogin");
	newUser.setUserPassword("password");

	userRepository.save(newUser);

	newUser = new User();
	newUser.setUserId(System.currentTimeMillis());
        //error data too long
	newUser.setFirstName("TestFirstName1TestFirstName1TestFirstName1TestFirstNam");
	newUser.setLastName("TestLastName1");
	newUser.setDateofBirth(new SimpleDateFormat("yyyy-MM-dd").parse("1976-01-09"));
	newUser.setEmailId("test@test.com");
	newUser.setUserLoginId("testlogin");
	newUser.setUserPassword("password");

	userRepository.save(newUser);
}

First save call will succeed and second will fail. First call will not be rolled back and will be commited because we have not used transaction

6c. Test User Repository with @Transactional and error condition

@Test
@Transactional
public void testWihTransaction3() throws Exception {
	LOGGER.debug("Running testWihTransaction3()....");

	User newUser = new User();
	newUser.setUserId(System.currentTimeMillis());
	newUser.setFirstName("TestFirstName3");
	newUser.setLastName("TestLastName3");
	newUser.setDateofBirth(new SimpleDateFormat("yyyy-MM-dd").parse("1976-01-09"));
	newUser.setEmailId("test@test.com");
	newUser.setUserLoginId("testlogin");
	newUser.setUserPassword("password");

	userRepository.save(newUser);

	newUser = new User();
	newUser.setUserId(System.currentTimeMillis());
        //error data too long
	newUser.setFirstName("TestFirstName1TestFirstName1TestFirstName1TestFirstNam");
	newUser.setLastName("TestLastName1");
	newUser.setDateofBirth(new SimpleDateFormat("yyyy-MM-dd").parse("1976-01-09"));
	newUser.setEmailId("test@test.com");
	newUser.setUserLoginId("testlogin");
	newUser.setUserPassword("password");

	userRepository.save(newUser);
}

First save call will be rolled back due to error in second call

startTransaction|Began transaction (1) for test context 
[DefaultTestContext@5ceecfee testClass
.... 
transaction manager 
[org.springframework.orm.jpa.JpaTransactionManager@7cd4a4d7]; rollback [true]
SQL Error: 1406, SQLState: 22001
Data truncation: Data too long for column 'FIRST_NM' at row 1
endTransaction|Rolled back transaction for test context 
[DefaultTestContext@5ceecfee testClass = UserRepositoryTest1
....

 

by , on August 6th, 2017

  • Categories