[JAVA] Spring Data JDBC Preview

(Added on 2019/01/02) This article has not been updated

** Most of the code in this article doesn't work anymore. I will keep it for the record, but there are no plans to update it. ** ** Please refer to the Official Document if you need reliable information.

@ kazuki43zoo has written a wonderful commentary, so I recommend you to read that as well. I tried Spring Data JDBC 1.0.0.BUILD-SNAPSHOT (-> 1.0.0.RELEASE)

Also, Spring Data JDBC is still a growing project. The following links may be useful, as some information cannot be traced by the published document alone.


I have a project called Spring Data JDBC, so I will try it.

Speaking of RDB access of Spring, JdbcTemplate and [Spring Data JPA](https://projects.spring.io/spring-data- There are jpa /) and so on. Although still at CRUD support level, Spring Data JDBC may also be a viable option for DB access in the future.

The source I tried this time is here.

!!! As of January 2018, Spring Data JDBC is BUILD-SNAPSHOT. There is a good chance that the code in this article will get stuck in the future. !!!

environment

pom.xml

After creating the Spring Boot project, add the dependency to pom.xml. DB should be H2 Database.

pom.xml


		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jdbc</artifactId>
			<version>1.0.0.BUILD-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>

table definition

Write the table definition in schema.sql.

schema.sql


create table employee (
    employee_number bigint primary key auto_increment,
    firstname varchar NOT NULL,
    lastname varchar NOT NULL,
    age int NOT NULL,
    hired_at date
);

Creating Repository

Create the entity class corresponding to the table. Annotate the ID field with @Id. (I use Lombok because it was troublesome to write Getter / Setter w)

Employee.java


@Data
public class Employee {

    @Id
    private Long employeeNumber;
    private String firstname;
    private String lastname;
    private Integer age;
    private LocalDate hiredAt;

}

After creating the entity, create a Repository that inherits CrudRepository.

EmployeeRepository.java


public interface EmployeeRepository extends CrudRepository<Employee, Long> {
}

Bean definition

How to run Spring Data JDBC

will become necessary. If you want the column name to be a snake case, define a NamingStrategy that converts the field name <=> column name of the entity.

SpringDataJdbcDemoApplication.java


@SpringBootApplication
@EnableJdbcRepositories
public class SpringDataJdbcDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringDataJdbcDemoApplication.class, args);
	}

	@Autowired
	JdbcMappingContext context;
	@Autowired
	DataSource datasource;

	@Bean
	DataAccessStrategy dataAccessStrategy() {
	    return new DefaultDataAccessStrategy(
	            new SqlGeneratorSource(context),
	            new NamedParameterJdbcTemplate(datasource),
	            context);
	}

	@Bean
	NamingStrategy namingStrategy() {
	    return new CustomNamingStrategy();
	}
}

CustomNamingStrategy.java


public class CustomNamingStrategy extends DefaultNamingStrategy {

    @Override
    public String getColumnName(JdbcPersistentProperty property) {
        String propertyName = property.getName();
        return camelToSnake(propertyName);
    }

    @Override
    public String getTableName(Class<?> type) {
        return super.getTableName(type);
    }

    public String camelToSnake(String original) {
        char[] chars = original.toCharArray();
        char[] buff = new char[chars.length + 10];

        int j = 0;
        for(int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if(buff[buff.length - 1] != ' ') {
                buff = Arrays.copyOf(buff, buff.length + 10);
            }
            if (Character.isUpperCase(c)) {
                buff[j++] = '_';
                buff[j++] = Character.toLowerCase(c);
            } else {
                buff[j++] = c;
            }
        }
        return new String(buff).trim();
    }

}

Try to move

I will move it at once.

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class SpringDataJdbcDemoApplicationTests {

    @Autowired
    EmployeeRepository repo;

    @Test
    public void contextLoads() {
    }

    @Test
    public void test1() {
        Employee employee = new Employee();
        employee.setFirstname("John");
        employee.setLastname("Do");
        employee.setAge(30);
        employee.setHiredAt(LocalDate.of(2012, 4, 1));

        // Insert
        employee = repo.save(employee);
        Long employeeNumber = employee.getEmployeeNumber();

        Optional<Employee> insertedOpt = repo.findById(employeeNumber);
        assertTrue(insertedOpt.isPresent());
        Employee inserted = insertedOpt.get();
        assertAll("insert",
                () -> assertEquals(inserted.getEmployeeNumber(), employeeNumber),
                () -> assertEquals(inserted.getFirstname(), "John"),
                () -> assertEquals(inserted.getLastname(), "Do"),
                () -> assertEquals(inserted.getAge(), Integer.valueOf(30)),
                () -> assertEquals(inserted.getHiredAt(), LocalDate.of(2012, 4, 1)));

        // Update
        employee.setAge(31);
        repo.save(employee);

        Optional<Employee> updatedOpt = repo.findById(employeeNumber);
        assertTrue(updatedOpt.isPresent());
        Employee updated = updatedOpt.get();
        assertEquals(updated.getAge(), Integer.valueOf(31));

        // Delete
        repo.delete(employee);

        Optional<Employee> deleted = repo.findById(employeeNumber);
        assertTrue(!deleted.isPresent());
    }
}

MyBatis cooperation

I haven't tried it, but it seems possible to link it with MyBatis. When the Repository method is called, it seems that the Mapper method with the corresponding name is executed.

Recommended Posts

Spring Data JDBC Preview
I tried Spring Data JDBC 1.0.0.BUILD-SNAPSHOT (-> 1.0.0.RELEASE)
spring data dynamodb trap
Try using Spring JDBC
Compatibility of Spring JDBC and MyBatis with Spring Data JDBC (provisional)
[spring] Let's use Spring Data JPA
Use Spring JDBC with Spring Boot
[How to install Spring Data Jpa]
Note that Insert could not be done with Spring Data JDBC
Spring Data JPA SQL log output
OR search with Spring Data Jpa Specification
Null support cache in Spring Data Redis
To write Response data directly in Spring