开发中热部署
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> ————————————————
使用 JPA
1、依赖
pom.xml
<!--数据库相关--> <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.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
2、配置数据源
application.properties
# 数据源配置 spring.datasource.url=jdbc:mysql://localhost:3306/data?useSSL=false&serverTimezone=CTT spring.datasource.username=root spring.datasource.password=123456 # 打印出 sql 语句 spring.jpa.show-sql=true #一定要不要在生产环境使用 ddl 自动生成表结构 spring.jpa.hibernate.ddl-auto=create spring.jpa.open-in-view=false # 创建的表的 ENGINE 为 InnoDB spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect
配置选项 spring.jpa.hibernate.ddl-auto
这个属性常用的选项有四种:
create: 每次重新启动项目都会重新创新表结构,会导致数据丢失
create-drop: 每次启动项目创建表结构,关闭项目删除表结构
update: 每次启动项目会更新表结构
validate: 验证表结构,不对数据库进行任何更改
一定要不要在生产环境使用 ddl 自动生成表结构
3、实体类
package com.example.demo.entity; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity @Data @NoArgsConstructor public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true) private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } }
启动服务的时候 Hibernate 会打印出建表语句
drop table if exists person create table person ( id bigint not null auto_increment, age integer, name varchar(255), primary key (id) ) engine=InnoDB alter table person add constraint UK_p0wr4vfyr2lyifm8avi67mqw5 unique (name)
4、创建 Repository 接口
package com.example.demo.repository; import com.example.demo.entity.Person; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.Optional; @Repository public interface PersonRepository extends JpaRepository<Person, Long> { // where name = ? Optional<Person> findByName(String name); // 查询部分属性 @Query("select p.name from Person p where p.id = :id") String findNameById(Long id); // 查询全部属性 @Query("select p from Person p where p.id = :id") Person findPersonById(Long id); // 更新 需要额外添加两个注解 // javax.persistence.TransactionRequiredException: Executing an update/delete query @Transactional @Modifying @Query("update Person p set p.name = :name where id = :id") void updateNameById(Long id, String name); }
5、创建控制器
省略 Service 服务层
package com.example.demo.controller; import com.example.demo.entity.Person; import com.example.demo.repository.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.Optional; @RestController public class PersonController { @Autowired PersonRepository personRepository; // 保存用户到数据库(无id), 全量更新数据(有id) @PostMapping("/person") public Person addPerson(@RequestBody Person person){ personRepository.save(person); return person; } // 根据 id 查找用户 @GetMapping("/person/{id}") public Person findPerson(@PathVariable("id") Long id){ Optional<Person> optional = personRepository.findById(id); if(optional.isPresent()){ return optional.get(); } else{ return null; } } // 根据 id 删除用户 @DeleteMapping("/person/{id}") public Map<String, Object> deletePerson(@PathVariable("id") Long id){ personRepository.deleteById(id); Map<String, Object> map = new HashMap<>(); map.put("result", "ok"); return map; } // 根据名字查询 @GetMapping("/findPersonByName") public Person findPersonByName(@RequestParam("name") String name){ Optional<Person> person = personRepository.findByName(name); if(person.isPresent()){ return person.get(); } else{ return null; } } // 根据id查找name @GetMapping("/findNameById") public Map<String, Object> findNameById(@RequestParam("id") Long id){ String name = personRepository.findNameById(id); Map<String, Object> map = new HashMap<>(); map.put("name", name); return map; } // 根据id查找person @GetMapping("/findPersonById") public Person findPersonById(@RequestParam("id") Long id){ Person person = personRepository.findPersonById(id); return person; } // 更新name字段 @PostMapping("/updateNameById") public Person updateNameById(@RequestBody Person person){ personRepository.updateNameById(person.getId(), person.getName()); return person; } }
连表、分页查询
实体类
@Entity @Data @NoArgsConstructor public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true) private String name; private Integer age; private Integer schoolId; private Integer companyId; } @Entity @Data @NoArgsConstructor @AllArgsConstructor public class Company { @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; @Column(unique = true) private String name; } @Entity @Data @NoArgsConstructor @AllArgsConstructor public class School { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true) private String name; }
DTO 对象
@Data @Builder(toBuilder = true) @NoArgsConstructor @AllArgsConstructor public class PersonDTO { private String name; private Integer age; private String companyName; private String schoolName; }
查询 Person 的基本信息
有一个 new 对象的操作
// 连接查询 @Query("select new com.example.demo.dto.PersonDTO(p.name, p.age, c.name, s.name) " + "from Person p left join Company c on p.companyId = c.id " + "left join School s on p.schoolId = s.id " + "where p.id = :personId") Optional<PersonDTO> findPersonInfo(@Param("personId") Long personId); // 分页查询 @Query( value = "select new com.example.demo.dto.PersonDTO(p.name, p.age, c.name, s.name) " + "from Person p left join Company c on p.companyId = c.id " + "left join School s on p.schoolId = s.id ", countQuery = "select count(p.id) " + "from Person p left join Company c on p.companyId = c.id " + "left join School s on p.schoolId = s.id" ) Page<PersonDTO> findPersonInfoPage(Pageable pageable);
使用
@GetMapping("/findPersonInfo") public PersonDTO findPersonInfo(@RequestParam("id") Long id){ Optional<PersonDTO> optional = personRepository.findPersonInfo(id); if(optional.isPresent()){ return optional.get(); } else{ return null; } } @GetMapping("/findPersonInfoPage") public Page<PersonDTO> findPersonInfoPage( @RequestParam("page") Integer page, @RequestParam("size") Integer size){ PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.DESC, "age"); Page<PersonDTO> personList = personRepository.findPersonInfoPage(pageRequest); return personList; }
between 查询
@Query("select p from Person p where p.age between :small and :big") List<Person> findPersonByBetween(int small, int big);