springboot 2 with JPA hello world CRUD example

1. Introduction

This post would demo how to do basic CRUD operations by using springboot 2 and JPA.

2. Environments

  • SpringBoot 2.0.2+
  • SpringBoot starter data jpa
  • MySQL connector java
  • Lombok
  • Java 1.8

3. The Pom.xml

spring boot version:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

all dependencies:

<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>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

4. The dependencies explanation

4.1 The lombok

The lombok is an IDE plugin to help you do some boliertemplate jobs. In this post we use the lombok to generate the getter/setter of the domain object.

You can refer to this post to learn how to use lombok.

5. The project layout

sbjh_layout

6. The database , table and initial data

For demo purpose, I setup one database in localhost as follows:

CREATE DATABASE `test` CHARACTER SET utf8 COLLATE utf8_bin;

There is a table ‘tbl_student’ in both of the databases:

CREATE TABLE `tbl_student` (
  `ID` int(10) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(100) NOT NULL,
  `BRANCH` varchar(255) NOT NULL,
  `PERCENTAGE` int(3) NOT NULL,
  `PHONE` int(10) NOT NULL,
  `EMAIL` varchar(255) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

And insert five records into that table:

INSERT INTO `tbl_student` (`ID`, `NAME`, `BRANCH`, `PERCENTAGE`, `PHONE`, `EMAIL`)
VALUES
    (1, 'jack', 'it', 20, 1211232, '[email protected]'),
    (2, 'mark', 'dev', 30, 333, '[email protected]'),
    (3, 'tony', 'dev', 2, 444, '[email protected]'),
    (4, 'nancy', 'dev', 23, 788, '[email protected]'),
    (5, 'tommy', 'it', 32, 2423, '[email protected]'),
    (6, 'tom', 'it', 23, 11, '[email protected]'),
    (7, 'Aka', 'dev', 1, 2, '[email protected]'),
    (8, 'al', 'dev', 2, 3, '[email protected]'),
    (9, 'ben', 'dev', 3, 4, '[email protected]'),
    (10, 'Mike', 'it', 5, 6, '[email protected]'),
    (11, 'Cow', 'it', 3, 23, '[email protected]');

7. The domain class Student

import lombok.Data;
@Data
@Entity
@Table(name="tbl_student")
public class Student {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private long id;
    private String name;
    private String branch;
    private int percentage;
    private int phone;
    private String email;

}
  • Here we use the lombok @Data annotation to generate getter/setter and constructors for the Student class.
  • We define the id property as the @Id of the table ,and specify the GenerationType.IDENTITY to it, which means the id is auto-increment.
  • We define the table name by @Table annotation

7. The app codes

7.1 the application.properties

Supply these properties in your application.properties:

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = 123456

7.3 The StudentRepository interface

The dao.StudentRepository is as follows:

public interface StudentRepository extends CrudRepository<Student,Long> {
}
  • The class StudentRepository only extends from the CrudRepository ,there is no need to define any other methods to implement the CRUD operations.

7.5 The testcase

The StudentRepositoryTest class would test the CRUD operations and find operations:

@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentRepositoryTest {
    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void testFindAll() {
        Iterable<Student> studentList = studentRepository.findAll();
        for(Iterator<Student> iter = studentList.iterator();iter.hasNext();) {
            Student student = iter.next();
            if(student!=null) {
                System.out.println(student);
            }
        }
        assertTrue(studentList!=null);
    }

    @Test
    public void testFindByProperty() {
        Optional<Student> student = studentRepository.findById(2l);
        assertTrue(student.get()!=null);
    }

    @Test
    public void testCount() {
        long count  = studentRepository.count();
        assertTrue(count>0);
    }

    @Test
    public void testCRUD() {
        Student s = new Student();
        s.setBranch("branchnew");
        s.setEmail("[email protected]");
        s.setName("Jerry");
        s.setPercentage(21);
        s.setPhone(982393);

        //insert the record
        Student ss = studentRepository.save(s);
        assertTrue(ss.getId()>0);

        //update the record
        ss.setBranch("branch_new2");
        studentRepository.save(ss);

        //query the updated record
        Optional<Student> ss2 = studentRepository.findById(ss.getId());
        assertTrue(ss2.get()!=null&&ss2.get().getBranch().equals("branch_new2"));

        //delete the record
        studentRepository.delete(ss2.get());
        Optional<Student> ss3 = studentRepository.findById(ss.getId());
        assertTrue(!ss3.isPresent());
    }
}

Run the testcase, we got a green bar. junit_greenbar

It’s so easy, do you think so?

The example source code has been uploaded to github, you can visit here to view the example source codes.