SpringDataJPA 入门教程

SpringData JPA

项目介绍

环境准备

Application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/database
    username: MYSQL_USER
    password: MYSQL_PWD
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.community.dialect.MySQLDialect
        format_sql: true
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/postgres
    username: postgres
    password: your_password
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.community.dialect.SQLiteDialect
        format_sql: true
spring:
  datasource:
    url: DB_PATH
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.community.dialect.SQLiteDialect
        format_sql: true

pom.xml

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

    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>p6spy</groupId>
        <artifactId>p6spy</artifactId>
        <version>3.9.1</version>
    </dependency>

    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.45.3.0</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

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

项目编写

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@Entity(name = "Author") // 用于将一个普通的 Java 类标识为一个 JPA 实体(entity)
public class Author {
    @Id
    // MySQL 下的主键自增,如果是 PostgreSQL 需要配置序列生成器
    @GeneratedValue(
            strategy = GenerationType.IDENTITY
    )
    private Long id;
    @Column(
            name = "first_name",
            nullable = false
    )
    private String firstName;
    @Column(
            name = "last_name",
            nullable = false
    )
    private String lastName;
    @Column(
            name = "email",
            unique = true,
            nullable = false
    )
    private String email;
    @Column(
            name = "age",
            nullable = false
    )
    private Integer age;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@Entity(name = "Book")
public class Book {
    @Id
    @GeneratedValue(
            strategy = GenerationType.IDENTITY
    )
    private Long id;
//    private Long authorId; // Book 与 Author 为一对多关系
    @Column(
            name = "title",
            nullable = false
    )
    private String title;
    @Column(
            name = "type"
    )
    @Enumerated(EnumType.STRING)
    private BookType type;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@Entity(name = "IdCard")
public class IdCard {
    @Id
    @GeneratedValue(
            strategy = GenerationType.IDENTITY
    )
    private Long id;
    @Column(
            name = "number",
            unique = true
    )
    private String number;
    @Column(
            name = "sex"
    )
    private Integer sex;
    @Column(
            name = "address",
            nullable = false
    )
    private String address;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@Entity(name = "Publisher")
public class Publisher {
    @Id
    @GeneratedValue(
            strategy = GenerationType.IDENTITY
    )
    private Long id;
    @Column(
            name = "address",
            nullable = false
    )
    private String address;
    @Column(
            name = "contact",
            unique = true
    )
    private String contact;
}
@Getter
@RequiredArgsConstructor
public enum BookType {
    FICTION("FIC", "Fiction"),
    NON("NF", "Non-Fiction"),
    SCIENCE("SCI", "Science"),
    HISTORY("HIS", "History"),
    FANTASY("FAN", "Fantasy"),
    BIOGRAPHY("BIO", "Biography");

    private final String code;
    private final String description;

    private static final Map<String, BookType> BY_CODE = new HashMap<>();

    static {
        for (BookType bookType : values()) {
            BY_CODE.put(bookType.code, bookType);
        }
    }

    public static BookType valueOfCode(String code) {
        return BY_CODE.get(code);
    }

}

关联关系

OneToOne

表示对象之间的一对一关系,可以放在字段上面。 - 如果配置双向关联,维护关联关系的是拥有外键的一方,另一方必须配置 mappedBy。 - 如果配置单向关联,直接配置在拥有外键的一方即可。

测试数据

使用 faker 来生成一些数据写入数据库:

<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>

在 MainApplication.java 中编写如下代码:

@Bean
CommandLineRunner commandLineRunner(AuthorRepository authorRepository) {
return args -> {
genFakerData(authorRepository);
};
}

private void genFakerData(AuthorRepository authorRepository) {
Faker faker = new Faker();
for (int i = 0; i < 10; i++) {
Author author = Author.builder()
.id(null)
.firstName(faker.name().firstName())
.lastName(faker.name().lastName())
.email(faker.internet().emailAddress())
.age(faker.number().numberBetween(20, 80))
.build();
authorRepository.save(author);
}
}

附录

Docker 创建容器

以命令方式

docker run --name my-mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -p 3306:3306 \
  -d mysql:latest
# TODO 待补充