Spring Data JPA 学习

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 的继承结构

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

三、Repository接口

  方法名称命名规则查询

   @Query注解查询

   @Query注解完成修改

四、CrudRepository接口

五、PagingAndSortingRepository接口

六、JpaRepository接口

七、JpaSpecificationExecutor接口

八、自定义Repository接口


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

Repository:标识接口

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

PagingAndSortingRepository:用于分页和排序操作

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

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

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

二、首先了解下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到底是什么

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

我们看看SimpleJpaRepository是何方神圣?

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

这里只截取一部分,可以看出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( 关键字 )+ 属性名称 ( 属性名称的首字母大写 )+ 查询条件 ( 首字母大写 )
 
 
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);
        }
    }
}

八、自定义Repository接口

当Spring Data JPA提供的5种接口都不能满足我们的需求时,我们可以自定义repository接口。

首先创建一个我们自定义的接口,里面写上我们需要完成的功能的方法

package com.zxw.dao;

import com.zxw.pojo.Users;

public interface MyRepository {
    public Users findById(Integer userid);
}

之后把原先的UsersDao也继承我们的自定义接口MyRepository

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;


public interface UsersDao extends JpaRepository<Users,Integer>, JpaSpecificationExecutor<Users>,MyRepository {

}

此时我们自定义接口中的方法并没有谁去实现它,所以我们写个接口实现类去实现,接口类为UsersDaoImpl

package com.zxw.dao;

import com.zxw.pojo.Users;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class UsersDaoImpl implements MyRepository {
    @PersistenceContext(name = "entityManagerFactory")
    private EntityManager entityManager;
    @Override
    public Users findById(Integer userid) {
        return this.entityManager.find(Users.class,userid);
    }
}

测试类

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

    @Test
    public void test1(){
        Users users = this.usersDao.findById(7);
        System.out.println(users);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值