Accessing Data with JPA
目标
学习JPA框架在关系型数据库中如何存储和检索数据。
环境
JDK 1.8+
Maven 3.2+
IDE(eclipse/idea)
内容
新建gs-accessing-data-jpa工程
使用idea新建工程步骤参考《springboot学习之构建 RESTful Web服务》()
添加依赖包:Spring Data Jpa和H2 Database
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
定义Entity
@Entity
public class Customer {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
- Customer有两个构造器,默认的构造器定义为protected只用于JPA,另一个构造器用于创建保存到数据库的Customer实例。
- @Entity注解用于标注是一个JPA实体,表示该实体映射表customer。
- Customer类中使用@Id注解标识主键,使用@GeneratedValue标识自动生成id,配置strategy为GenerationType.AUTO用于自动选择一个最适合底层数据库的主键生成策略。
- 另外两个字段firstName和lastName,表中映射字段分别为first_name和last_name。
定义CustomerRepository接口
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
Customer findById(long id);
}
CustomerRepository继承CrudRepository接口,通过继承CrudRepository实现了保存、删除和查询等方法。Spring Data JPA允许定义其它的查询方法,例如:findByLastName。
创建Application
@SpringBootApplication
public class GsAccessingDataJpaApplication {
private static final Logger log = LoggerFactory.getLogger(GsAccessingDataJpaApplication.class);
public static void main(String[] args) {
SpringApplication.run(GsAccessingDataJpaApplication.class, args);
}
}
@SpringBootApplication包含下面三个注解:
- @Configuration:装配bean的配置文件
- @EnableAutoConfiguration:启用Spring应用程序上下文配置
- @ComponentScan:扫描GsAccessingDataJpaApplication所在包下的其他组件
修改Application类,加入如下方法:
@Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a few customers
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
// fetch all customers
log.info("Customers found with findAll():");
log.info("-------------------------------");
for (Customer customer : repository.findAll()) {
log.info(customer.toString());
}
log.info("");
// fetch an individual customer by ID
Customer customer = repository.findById(1L);
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(customer.toString());
log.info("");
// fetch customers by last name
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
// for (Customer bauer : repository.findByLastName("Bauer")) {
// log.info(bauer.toString());
// }
log.info("");
};
}
运行日志
2022-05-17 17:38:07.448 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customers found with findAll():
2022-05-17 17:38:07.448 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : -------------------------------
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=1, firstName='Jack', lastName='Bauer'}
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=2, firstName='Chloe', lastName='O'Brian'}
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=3, firstName='Kim', lastName='Bauer'}
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=4, firstName='David', lastName='Palmer'}
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=5, firstName='Michelle', lastName='Dessler'}
2022-05-17 17:38:07.559 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication :
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer found with findById(1L):
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : --------------------------------
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=1, firstName='Jack', lastName='Bauer'}
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication :
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer found with findByLastName('Bauer'):
2022-05-17 17:38:07.571 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : --------------------------------------------
2022-05-17 17:38:07.616 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=1, firstName='Jack', lastName='Bauer'}
2022-05-17 17:38:07.616 INFO 15660 --- [ main] c.example.GsAccessingDataJpaApplication : Customer{id=3, firstName='Kim', lastName='Bauer'}
H2改为Mysql
之前是使用H2数据库做的,Customer怎么映射的数据表问题还不明白,所以再使用mysql数据库试验一下。
- 屏蔽h2依赖包,添加mysql依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- yml文件配置:
spring:
jpa:
hibernate:
ddl-auto: update
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: root
Entity、Repository和Application都不改变,运行后跟H2数据库一切正常。查看mysql库,发现数据库如下:
customer之前没有这个表,运行之后库中新建了customer表。这是因为使用如下配置项,spring.jpa.hibernate.ddl-auto: update,使用内嵌数据库时或者没有schema manager被检测到时为create-drop模式,否则为none模式。这里分别介绍下几种模式区别:
create: 先删除现有表的数据和结构,新建表然后再新建表上操作
validate: 验证表结构,不存在会引发异常
update: 检查表和列,不存在会创建
create-drop:检查表并操作,操作完后删除
none: 不做表的操作
总结
- 实体类相关注解的使用
- Repository接口的使用及扩展
- spring.jpa.hibernate.ddl-auto的配置