创建一个SpringBoot项目
1. 引入依赖
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</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>
2. 数据库
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`clazz` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`address` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
3. 实体类
注意要使用注解@Entity
标识实体类,以及@Id
注解标识主键,主键是自增字段还需要增加@GeneratedValue
。
在使用 JPA 进行开发时,如果使用了 @Id 注解来指定实体类的主键,并且主键类型为整型或长整型,那么 JPA 在创建表的时候会自动为这个主键生成一个序列(Sequence)。启动项目后可以看到在数据库中看到多了一张表student_seq
,表中字段为next_val
这个值就是下次的自增id值。
@Data
@Entity
public class Student {
@Id
@GeneratedValue
private Integer id;
private String name;
private String clazz;
private String address;
}
4. 持久化层
这个继承就像MyBatis-Plus的ServiceImpl,这个JpaRepository<Student,Integer>
给我们提供了一些通用的方法,我们也可以根据JPA的规则自定义我们所需要的方法,例如通过学生的姓名查询学生数据。
public interface StudentDao extends JpaRepository<Student,Integer> {
// 自定义根据名称查询学生数据
List<Student> findByName(String name);
}
除了使用命名查询外,还可以使用 @Query 注解来编写自定义的 SQL 查询语句。例如:
public interface StudentDao extends JpaRepository<Student, Integer> {
@Query("SELECT s FROM Student s WHERE s.name = ?1")
List<Student> findByName(String name);
}
在这个例子中,使用 @Query
注解来指定了查询语句,其中 ?1
表示第一个参数(即方法参数中的 name)。当您调用 studentDao.findByName(“Tom”) 方法时,JPA 将会自动执行以下 SQL 查询语句:
SELECT * FROM student WHERE name = 'Tom'
注意,在使用 @Query 注解时,需要自己编写完整的 SQL 查询语句,因此需要更加谨慎地处理参数绑定和 SQL 注入等问题。
5. Service层
public interface StudentService {
Student insertStudent(Student student);
Student updateStudent(Student student);
void deleteStudent(Integer id);
Iterable<Student> getAll();
Iterable<Student> getByName(String name);
}
ServiceImpl层
@Service
public class StudentServiceImpl implements StudentService {
@Resource
StudentDao studentDao;
@Override
public Student insertStudent(Student student) {
return studentDao.save(student);
}
@Override
public Student updateStudent(Student student) {
return studentDao.save(student);
}
@Override
public void deleteStudent(Integer id) {
studentDao.deleteById(id);
}
@Override
public Iterable<Student> getAll() {
return studentDao.findAll();
}
@Override
public Iterable<Student> getByName(String name) {
return studentDao.findByName(name);
}
}
6. Controller层
@RestController
@RequestMapping("/studentController")
public class StudentController {
@Resource
StudentService studentService;
//新增数据
@RequestMapping("/saveAllStudent")
public Student saveAllStudent(){
Student student=new Student();
student.setName("张三");
student.setAddress("北京");
student.setClazz("软工4-1班");
return studentService.insertStudent(student);
}
//修改数据
@RequestMapping("/updateStudent")
public Student updateStudent(){
Student student=new Student();
student.setId(1);
student.setName("李四");
student.setAddress("上海");
student.setClazz("软工4-1班");
return studentService.updateStudent(student);
}
//删除数据
@RequestMapping("/deleteStudent")
public void deleteStudent(){
studentService.deleteStudent(2);
}
//查询数据
@RequestMapping("/getAllStudent")
public Iterable<Student> getAllStudent(){
return studentService.getAll();
}
//根据姓名查询数据
@RequestMapping("/listStudentByName")
public Iterable<Student> listStudentByName(String name){
return studentService.getByName(name);
}
}
7. 配置文件
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent-output=true
spring.jpa.database=mysql
8. 测试
启动项目后,测试接口。项目每启动一次后,student_seq
的next_val
字段会变化,避免id冲突。