欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Data JPA 学习

程序员文章站 2024-03-12 22:55:20
...

Spring Data JPA是个非常强大的ORM持久化解决方案,免去了mybatis或spring jdbcTemplate的开发人员编写脚本的无趣工作。

Spring Data JPA官方文档

https://docs.spring.io/spring-data/jpa/docs/2.0.9.RELEASE/reference/html/

一、首先了解下Spring Data JPA 的继承结构

Repository:标识接口

CrudRepository:用于CRUD操作(修改的方法和添加一样都是save,至于什么时候是修改,什么时候是添加后面会说)

PagingAndSortingRepository:用于分页和排序操作

JpaRepository:将其他接口的方法的返回值做适配处理

Spring Data JPA 学习

除了图中的内容,还必须掌握JpaSpecificationExecutor,该接口不在图中的关系中,起作用是多条件查询且支持分页和查询。

如果说有什么关系,请看下图

Spring Data JPA 学习

二、首先了解下Spring Data JPA 的运行原理(简单说下)

我们知道使用Spring Data JPA是不需要接口实现类的,但我们在测试类中自动注入的UsersDao到底是什么呢?

UsersDao接口

package com.zxw.dao;

import com.zxw.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;


public interface UsersDao extends JpaRepository<Users,Integer> {

}

测试类

package com.zxw.test;

import com.zxw.dao.UsersDao;
import com.zxw.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {

    @Autowired
    private UsersDao usersDao;

    @Test
    public void test() {
        System.out.println(usersDao);
        System.out.println(usersDao.getClass());
    }

}

我们通过简单输出看下UserDao到底是什么

Spring Data JPA 学习

从结果可以看出usersDao的类型是个代理类,usersDao是个SimpleJpaRepository对象。

我们看看SimpleJpaRepository是何方神圣?

Spring Data JPA 学习

可以看到SimpleJpaRepository实现了JpaRepository,JpaSpecificationExecutor接口,再看看有什么方法

Spring Data JPA 学习

这里只截取一部分,可以看出SimpleJpaRepository实现了相应的CURD操作。

其实我们自己也可以产生个代理对象:

@PersistenceContext(name="entityManagerFactory") 
    private EntityManager em; 
    @Test 
    public void test1(){ 
       
        JpaRepositoryFactory factory = new JpaRepositoryFactory(em); 
        //getRepository(UsersDao.class);可以帮助我们为接口生成实现类。而这个实现类是 SimpleJpaRepository 的对象 
        // 要求:该接口必须要是继承 Repository 接口 
        UsersDao ud = factory.getRepository(UsersDao.class); 
        System.out.println(ud); 
        System.out.println(ud.getClass()); 
        
    }

三、Repository接口

Repository接口是Spring Data JPA 中提供的所有接口的顶层接口

Repository提供了两种查询方式:

  • 基于方法名称命名规则查询
  • 基于@Query注解查询

  方法名称命名规则查询

   规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
 
Spring Data JPA 学习
Spring Data JPA 学习
Spring Data JPA 学习
 
public interface UsersDao extends Repository<Users,Integer> {
    //findBy关键字   Username属性名称   Is查询条件
    List<Users> findByUsernameIs(String username);
 
}

 

   @Query注解查询

  •      通过JPQL语句查询

            JPQL:通过 Hibernate HQL 演变过来的。他和 HQL 语法及其相似。

public interface UsersDao extends Repository<Users,Integer> {

    //JPQL
    @Query("from Users where username like ?")
    List<Users> selByLikeName(String username);

    @Query("from Users where userage > ?")
    List<Users> selByAge(Integer userage);

    @Query("from Users where username = ? and userage <= ?")
    List<Users> selNameAndAge(String username,Integer userage);

}
  •      通过SQL语句查询

            (前面没有写nativeQuery是因为我们所写的语句需要变成可以查询的sql语句,这里我们写的本身就是sql语句所以要开启nativeQuery)

public interface UsersDao extends Repository<Users,Integer> {

    //SQL
    //nativeQuery:默认的是 false.表示不开启 sql 查询。是否对 value 中的语句 做转义。

    @Query(value = "select * from t_users where username like ?",nativeQuery = true)
    List<Users> selByLikeNameSQL(String username);

    @Query(value = "select * from t_users where userage > ?",nativeQuery = true)
    List<Users> selByAgeSQL(Integer userage);

    @Query(value = "select * from t_users where username = ? and userage <=?",nativeQuery = true)
    List<Users> selNameAndAgeSQL(String username,Integer userage);
}

   @Query注解完成修改

     (一定要写@Modifying)

public interface UsersDao extends Repository<Users,Integer> {

    //修改
    @Query("update Users set userage = ? where userid = ?")
    @Modifying //代表这是更新
    void updUserageById(Integer userage,Integer userid);
}

四、CrudRepository接口

package com.zxw.dao;

import com.zxw.pojo.Users;

import org.springframework.data.repository.CrudRepository;


public interface UsersDao extends CrudRepository<Users,Integer> {

}

  测试代码

package com.zxw.test;

import com.zxw.dao.UsersDao;
import com.zxw.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {
    @Autowired
    private UsersDao usersDao;

    /**
     * 插入单条数据
     */
    @Test
    public void save(){
        Users users=new Users();
        users.setUsername("金泰妍");
        users.setUserage(20);
        this.usersDao.save(users);
    }
    /**
     * 插入多条数据
     */
    @Test
    public void saveMany(){
        Users users1=new Users();
        users1.setUsername("林允儿");
        users1.setUserage(30);

        Users users2=new Users();
        users2.setUsername("徐珠贤");
        users2.setUserage(25);

        List<Users> list=new ArrayList<>();
        list.add(users1);
        list.add(users2);

        this.usersDao.save(list);
    }
    /**
     * 查询所有
     */
    @Test
    public void findAll(){
        List<Users> all = (List<Users>) this.usersDao.findAll();
        for (Users u:all) {
            System.out.println(u);
        }
    }

    /**
     * 查询单个
     */
    @Test
    public void findOne(){
        Users one = this.usersDao.findOne(3);
        System.out.println(one);
    }

    /**
     * 修改 方式一 
     */
    @Test
    public void updOne(){
        Users one = this.usersDao.findOne(3);
        one.setUsername("Vivian");
        this.usersDao.save(one);
    }
    /**
     * 修改 方式二  事务依赖本方法
     */
    @Test
    @Transactional
    @Rollback(false)
    public void updTwo(){
        Users one = this.usersDao.findOne(3);//持久化
        one.setUsername("Snow");

    }
    /**
     * 删除
     */
    @Test
    public void del(){
        this.usersDao.delete(8);
    }
}

五、PagingAndSortingRepository接口

package com.zxw.dao;

import com.zxw.pojo.Users;

import org.springframework.data.repository.PagingAndSortingRepository;


public interface UsersDao extends PagingAndSortingRepository<Users,Integer> {

}

测试类

package com.zxw.test;

import com.zxw.dao.UsersDao;
import com.zxw.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {
    @Autowired
    private UsersDao usersDao;
    /**
     * 分页
     */
    @Test
    public void page(){
        int page=0;//页数索引  从0开始
        int size=2;//一页几条数据

        //分页
        Pageable pageable=new PageRequest(page,size);
        Page<Users> usersPage = this.usersDao.findAll(pageable);

        System.out.println("总条数:"+usersPage.getTotalElements());
        System.out.println("总页数:"+usersPage.getTotalPages());
        List<Users> users = usersPage.getContent();
        for (Users u:users) {
            System.out.println(u);
        }
    }
    /**
     * 分页+排序
     */
    @Test
    public void pageAndSort(){
        int page=0;//页数索引  从0开始
        int size=2;//一页几条数据

        //排序
        Sort sort=new Sort(Sort.Direction.DESC,"userage");
        //分页
        Pageable pageable=new PageRequest(page,size,sort);
        Page<Users> usersPage = this.usersDao.findAll(pageable);

        System.out.println("总条数:"+usersPage.getTotalElements());
        System.out.println("总页数:"+usersPage.getTotalPages());
        List<Users> users = usersPage.getContent();
        for (Users u:users) {
            System.out.println(u);
        }
    }
    /**
     * 排序 单条件
     */
    @Test
    public void sortTest(){
        //Sort:该对象封装了排序规则以及指定的排序字段(对象的属性来表示)
        // direction:排序规则
        // properties:指定做排序的属性
        Sort sort = new Sort(Sort.Direction.DESC,"userage");
        List<Users> list = (List<Users>)this.usersDao.findAll(sort);
        for (Users users : list) {
            System.out.println(users);
        }
    }

    /**
     * 排序 多条件
     */
    @Test
    public void sort2Test(){
        //Sort:该对象封装了排序规则以及指定的排序字段(对象的属性来表示)
        // direction:排序规则
        // properties:指定做排序的属性
        //多条件查询时使用,一个order代表一个条件
        Sort.Order order=new Sort.Order(Sort.Direction.DESC,"userage");
        Sort.Order order1=new Sort.Order(Sort.Direction.ASC,"username");
        Sort sort = new Sort(order,order1);
        List<Users> list = (List<Users>)this.usersDao.findAll(sort);
        for (Users users : list) {
            System.out.println(users);
        }
    }


}

六、JpaRepository接口

package com.zxw.dao;

import com.zxw.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;


public interface UsersDao extends JpaRepository<Users,Integer> {

}

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {
    @Autowired
    private UsersDao usersDao;


    /*** 添加用户 */
    @Test
    @Transactional
    // 在测试类对于事务提交方式默认的是回滚。
    @Rollback(false)//取消自动回滚
    public void testInsertUsers() {
        Users users = new Users();
        users.setUserage(18);
        users.setUsername("凑崎纱夏");
        this.usersDao.save(users);
    }

}

七、JpaSpecificationExecutor接口

package com.zxw.dao;

import com.zxw.pojo.Users;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * JpaSpecificationExecutor不能单独使用
 */
public interface UsersDao extends JpaRepository<Users,Integer>, JpaSpecificationExecutor<Users> {

}

测试类

package com.zxw.test;

import com.zxw.dao.UsersDao;
import com.zxw.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sound.midi.Soundbank;
import java.util.ArrayList;
import java.util.List;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {
    @Autowired
    private UsersDao usersDao;

    /**
     * 单条件查询
     */
    @Test
    public void test1(){

        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                /**
                 * @return Predicate:定义了查询条件
                 * @param Root<Users> root:封装查询条件的对象
                 * @param CriteriaQuery<?> query:定义了一个基本的查询.一般不使用
                 * @param CriteriaBuilder cb:创建一个查询条件
                 */
                Predicate predicate = criteriaBuilder.equal(root.get("username"), "金泰妍");
                return predicate;
            }
        };
        List<Users> list = this.usersDao.findAll(spec);
        for (Users u:list) {
            System.out.println(u);
        }
    }

    /**
     * 多条件查询  方式一
     * 需求:使用用户姓名以及年龄查询数据
     */
    @Test
    public void test2(){

        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list=new ArrayList<>();
                list.add(criteriaBuilder.equal(root.get("username"),"金泰妍"));
                list.add(criteriaBuilder.equal(root.get("userage"),20));

                Predicate[] arr=new Predicate[list.size()];
                return criteriaBuilder.or(list.toArray(arr));
            }
        };
        List<Users> list = this.usersDao.findAll(spec);
        for (Users u:list) {
            System.out.println(u);
        }
    }

    /**
     * 多条件查询  方式二
     */
    @Test
    public void test3(){

        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.or(criteriaBuilder.equal(root.get("username"),"金泰妍"),criteriaBuilder.equal(root.get("userage"),20));
            }
        };
        List<Users> list = this.usersDao.findAll(spec);
        for (Users u:list) {
            System.out.println(u);
        }
    }

    /**
     * 多条件查询  方式二加分页
     */
    @Test
    public void test4(){

        Specification<Users> specification = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("username").as(String.class),"金%");
            }
        };
        //分页
        Pageable pageable=new PageRequest(0,2);
        Page<Users> all = this.usersDao.findAll(specification, pageable);

        List<Users> list = all.getContent();
        System.out.println(all.getTotalElements());
        System.out.println(all.getTotalPages());

        for (Users u:list) {
            System.out.println(u);
        }
    }

    /**
     * 多条件查询  方式二加排序
     */
    @Test
    public void test5(){

        Specification<Users> specification = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("username").as(String.class),"金%");
            }
        };
        //排序
        Sort sort=new Sort(Sort.Direction.DESC,"userage");
        List<Users> all = this.usersDao.findAll(specification, sort);
        for (Users u:all) {
            System.out.println(u);
        }
    }

    /**
     * 多条件查询  方式二 排序+分页
     *   排序放入分页中
     */
    @Test
    public void test6(){

        //排序
        Sort sort=new Sort(Sort.Direction.ASC,"userage");
        //分页
        Pageable pageable=new PageRequest(0,2,sort);
        //多条件查询
        Specification<Users> specification=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("username").as(String.class),"金%");
            }
        };

        Page<Users> all = this.usersDao.findAll(specification, pageable);
        for (Users u:all) {
            System.out.println(u);
        }
    }
}

 

相关标签: Spring Data JPA