导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 配置数据库的jar包 spring-boot不会给数据库的架包加载进去-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test?useunicode=true&characterEncoding=utf8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update,validate)
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql
:是否显示sql语句spring.jpa.hibernate.ddl-auto
:
ddl-auto:create
----每次运行该程序,没有表格会新建表格,表内有数据会清空ddl-auto:create-drop
----每次程序结束的时候会清空表ddl-auto:update
----每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新ddl-auto:validate
----运行程序会校验数据与数据库的字段类型是否相同,不同会报错
实体类Student
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "student_info")
public class Student {
@Id
@Column(name="student_id")
private int id;
@Column(name = "student_name")
private String name;
@Column(name = "student_age")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Entity:
标识这是一个实体类@id:
标识该属性对应表中的id@Column:
属性名对应的字段名@Table:
该实体类对应的表名
创建对应的数据库
CREATE TABLE `student_info` (
`student_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`student_name` varchar(32) DEFAULT NULL COMMENT '姓名',
`student_age` int(11) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`student_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
dao层StudentMapper接口,有两种方法实现hibernate。分别继承JpaRepository和CrudRepository
先使用CrudRepository,代码如下
import com.tpy.boothibernater.entity.Student;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
@Component
public interface StudentMapper extends CrudRepository<Student, Integer> {
}
查看CrudRepository<Student, Integer>
源码
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
}
-
通过这些方法名,就可以猜测到,都是增删修查的方法
-
T对应就是Student(你的实体类),ID就是对应的Id类型
-
用过mybatis就知道,我们需要写mapper接口和对应的xml配置文件,但是这里就是只要你的mapper接口继承这个接口就可以。就连xml文件都不用写。
-
其实mybatis-plus也是这样,只需要写mapper,继承一个接口,接口提供简单增删修查,不需要写xml配置文件,但是复杂的语句同样要写xml文件
-
同样hibernate复杂的语句也需要写sql语句,这个后面在说
-
这个接口里面有一个
Optional<T>
类,这个类是jdk1.8添加的,这是一i个包装类,里面可以存放null,它可以避免我们直接调用null,防止null指针异常。当然,我们也可以通过
T t = optional.get();
方法获取到存放在里面的对象
Service层
- 接口
import com.tpy.boothibernater.entity.Student;
import java.util.List;
public interface StudentService {
/**
* 添加
*/
void insertStudent(Student student);
/**
* 删除
*/
void deleteStudent(int id);
/**
* 修改
*/
void updateStudent(Student student);
/**
* 查询
*/
List<Student> getStudent();
/**
* 查询单个
*/
Student getStudentById(int id);
}
实现类
import com.tpy.boothibernater.dao.StudentMapper;
import com.tpy.boothibernater.entity.Student;
import com.tpy.boothibernater.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
StudentMapper studentMapper;
@Override
public void insertStudent(Student student) {
studentMapper.save(student);
}
@Override
public void deleteStudent(int id) {
studentMapper.deleteById(id);
}
@Override
public void updateStudent(Student student) {
studentMapper.save(student);
}
@Override
public List<Student> getStudent() {
return (List<Student>) studentMapper.findAll();
}
@Override
public Student getStudentById(int id) {
Optional<Student> student = studentMapper.findById(id);
return student.get();
}
}
Controller
import com.tpy.boothibernater.entity.Student;
import com.tpy.boothibernater.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("hibernate")
public class HibernateController {
@Autowired
StudentService studentService;
/**
* 添加
* @return
*/
@RequestMapping("insert")
public String insert(){
Student student = new Student();
student.setId(21);
student.setAge(21);
student.setName("77");
studentService.insertStudent(student);
return "SUCCESS";
}
/**
* 删除
* @param id
* @return
*/
@RequestMapping("delete")
public String delete(int id){
studentService.deleteStudent(id);
return "SUCCESS";
}
/**
* 修改
* 修改跟添加调用的是同一个方法如果id相同就改变数据没有就创建数据
* @param student
* @return
*/
@RequestMapping("update")
public String update(Student student){
studentService.updateStudent(student);
return "SUCCESS";
}
/**
* 查询
* @return
*/
@RequestMapping("getStudent")
public List<Student> getStudent(){
return studentService.getStudent();
}
/**
* 根据id查询
* @param id
* @return
*/
@RequestMapping("studentId")
public Student getStudentById(int id){
return studentService.getStudentById(id);
}
}
如此简单的继承CrudRepository的实现方法就完成了
JpsRepository实现方法
重新创建一个mapper接口,继承JpaRepository
import com.tpy.boothibernater.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentMapperJpa extends JpaRepository<Student,Integer> {
}
- 这里的Student和Integer和CrudRepository相同,查看其源码,同样可以使用提供的方法
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
这里提供一个自定义sql
@Component
public interface StudentMapperJpa extends JpaRepository<Student,Integer> {
@Query(value = "select s.student_id ,s.student_name ,s.student_age " +
"from student_info s where student_name like concat('%',concat(?1,'%') )",nativeQuery=true)
public List<Student> selectLikeStudentByName(String name);
}
- 这里的
?1
,1
表示第几个参数
controller 直接调用
@RestController
public class TestController {
@Autowired
private StudentMapperJpa mapperJpa;
@RequestMapping("likeName")
public List<Student> findStudentByLikeName(String name){
return mapperJpa.selectLikeStudentByName(name);
}
}
Spring-data-jpa有一个特点,可以通过解析方法名字来自动生成SQL查询语句,不适合delete insert update,不适合动态查询
-
语法
-
也可以自己在@Query标签中写查询语句,注意,nativeQuery 是询问是否使用原生sql语句,默认nativeQuery为false
-
在@Query标签中使用原生SQL查询,nativeQuery设置为true
使用:name
传递参数
@Query(value = "select s.student_id,s.student_name,s.student_age " +
"from student_info s where s.student_name = :name",nativeQuery = true)
public Student selectStudentByName(@Param("name") String name);
分页查询
import com.tpy.boothibernater.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import org.springframework.data.domain.Pageable;
import java.util.List;
@Component
public interface StudentMapperJpa extends JpaRepository<Student,Integer> {
@Query(value = "select s.student_id ,s.student_name ,s.student_age " +
"from student_info s where student_name like concat('%',concat(?1,'%') )",nativeQuery=true)
public List<Student> selectLikeStudentByName(String name);
/*:name传递参数*/
@Query(value = "select s.student_id,s.student_name,s.student_age " +
"from student_info s where s.student_name = :name",nativeQuery = true)
public Student selectStudentByName(@Param("name") String name);
/*分页查询*/
@Query(value = "select s.student_id,s.student_name,s.student_age " +
"from student_info s",nativeQuery = true)
public List<Student> selectByNamePageable(Pageable pageable);
}
- controller
@RestController
public class TestController {
private static int CurrentPage = 0;
@Autowired
private StudentMapperJpa mapperJpa;
@RequestMapping("likeName")
public List<Student> findStudentByLikeName(String name){
return mapperJpa.selectLikeStudentByName(name);
}
@RequestMapping("findByName")
public Student findStudentByName(String name){
return mapperJpa.selectStudentByName(name);
}
@RequestMapping("selectPageable")
public List<Student> findStudentByNamePageable(){
Pageable page = PageRequest.of(CurrentPage++, 1, Sort.by("student_id"));
return mapperJpa.selectByNamePageable(page);
}
}
pageable
Pageable page = PageRequest.of(CurrentPage++, 1, Sort.by("student_id"));
public static PageRequest of(int page, int size, Sort sort) {
return new PageRequest(page, size, sort);
}
page
:当前页码size
:每页行数sort
:排序(升序、降序),student_id
:就是按该字段进行排序
最后就是上源码,一起学习吧
https://github.com/tangpengyi/boothibernater