springboot提供了很多种操作数据库的方式,大致思路都差别不大,只是使用的一些细节存在差异。
1.JpaRepository
spring data有一个分支为spring data JPA,是专门针对JPA操作数据库的模块。下图是官方网站:
里面封装了大量的核心库,比如 JpaRepository,我们只需要进行继承接口使用就行,不用对接口进行实现,直接就可以使用增删改查等操作,使用起来超级方便。下图为执行流程:
代码:
controller:
@RequestMapping("/getById")
public User getById(Integer id) {
return crudService.getById(id);
}
service:
public User getById(Integer id) {
Optional<User> f=resitory.findById(id);
return f.get();
}
Resitory:
public interface Resitory extends JpaRepository<User, Integer>{
}
注:这里是写的代码是很简答的,里面的方法是封装好的方法,故在Resitory看似没有执行逻辑。实际上,如果我使用的方法,在里面不存在,那么还是需要写抽象方法的,只不过,我们还是不用去写实现,比如模糊查询,只需要在方法后面加Like,系统是可以辨别是进行模糊查询的,因为内部有其识别机制。再比如多条件查询,可以加And,And后面的首字母要大写。
模糊查询:
Resitory层:
public interface Resitory extends JpaRepository<User, Integer>{
List<User> findByUserNameLike(String userName);
}
多条件查询:
Resitory层:
public interface Resitory extends JpaRepository<User, Integer>{
List<User> findByUserNameAndPassword(String userName, String password);
}
2.PagingAndSortingRepository
分页查询下,顾名思义,就是讲数据库内容进行分页显示,显示在不同的页面上。
代码:
service:
public List<User> sort() {
Sort sort=new Sort(Direction.DESC,"id");
return (List<User>) resitory.findAll(sort);
}
public Page<User> page(Integer pageindex) {
Sort sort=new Sort(Direction.DESC,"id");
PageRequest pageable=PageRequest.of(pageindex-1, 2,sort);
return resitory.findAll(pageable);
}
3.Query查询
上面的查询都是单表查询,我们在现实中,操作的表多为多表,使用Query注解进行查询,操作十分方便。
代码:
Resitory层:
public interface StudentRepository extends JpaRepository<Student, Integer>{
@Query("select c.name from Clazz c inner join c.students s "
+ "where s.name = ?1 ")
String getClazzByStuName(String name);
}
4.NamedQuery查询
NamedQuery查询查询与Query查询几乎一致的,只是注解的位置不同。
代码:
domian:
@NamedQuery(name="Student.getStuByClazzName",
query="select s from Student s where s.clazz.name like ?1")
public class Student implements Serializable{
........................这里的代码省略了
}
5.Specification动态查询
动态查询的思路也是蛮好理解,因为是动态查询所以需要提供能提供的条件,供使用者可以进行随意组合,达到“动态”的目的,这里的动态实际上可以理解为“灵活使用”。因此,我们需要在业务层停供尽可能提供的条件,每一个条件都要分为有(存在这个条件)或者无(不存在这个条件),因为我们可能不会使用或者使用这个条件,所以需要进行非空判断,然后具体到Specification来说,就是进行具体类似sql的java逻辑实现。具体的执行过程如下:
代码:
service层:
List<Student> students =
studentRepository.findAll(new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (student!=null) {
if(!StringUtils.isEmpty(student.getName())){
predicates.add(cb.like(root.<String> get("name"),
"%" + student.getName() + "%"));
}
if(!StringUtils.isEmpty(student.getAddress())){
predicates.add(cb.like(root.<String> get("address"),
"%" + student.getAddress() + "%"));
}
if(student.getSex() != '\0'){
predicates.add(cb.equal(root.<String> get("sex"),
student.getSex()));
}
if(student.getClazz()!=null && !StringUtils.
isEmpty(student.getClazz().getName())){
root.join("clazz", JoinType.INNER);
predicates.add(cb.like(root.get("clazz").get("name"),
"%"+student.getClazz().getName()+"%"));
}
}
return query.where(predicates.toArray
(new Predicate[predicates.size()])).getRestriction();
}
});
这里只是使用的java代替的sql语句,将条件全部封装在predicates中,然后查询(query.where())的时候进行组装成完整的sql
6.JDBCTemplate
虽然我们使用hibernate的全自动操作用起来很爽,但是毕竟hibernate会产生大量冗余的sql语句,导致系统的性能会受到影响,故springboot提供了一个我们自己写SQL的jdbc的template,使用起来更加灵活一些。具体的执行过程如下:
代码:
(这里只写插入操作,其余操作类似,代码只给了repository层的,因为其他层比较简单)
Repository层:
@Repository
public class UserRepository {
@Resource
private JdbcTemplate jdbcTemplate;
public int insertUser(){
String sql = "insert into tb_user(login_name ,user_name ,password) "
+ "values (?,?,?),(?,?,?),(?,?,?)";
Object[] args = new Object[]{"zgl","诸葛亮","123","smy","司马懿","456"
,"sq","孙权","789"};
return jdbcTemplate.update(sql, args);
}
}
application.properties:
# url
spring.datasource.url=jdbc:mysql://localhost:3306/jdbctemplate
# username
spring.datasource.username=root
# password
spring.datasource.password=
# driver
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
添加的pom依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
7.整合mybatis
使用注解做的时候,用法与@query方法一致,都是在Resitory层加带sql的注解,若使用mappering文件,只是不加注解,其他使用都一致。