美文网首页springboot
Spring Data学习day93:Spring Data J

Spring Data学习day93:Spring Data J

作者: 开源oo柒 | 来源:发表于2019-11-28 22:25 被阅读0次

一、Spring Data Jpa中的接口:

1.Repository接口:

Repository 接口是 Spring Data JPA 中为我我们提供的所有接口中的顶层接口,Repository 提供了两种查询方式的支持。
(1)基于方法名称命名规则查询;
(2)基于@Query 注解查询;

  • 规则:

findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)。

示例
示例
  • 创建接口:

继承Repository接口;方法的名称必须要遵循驼峰式命名规则。findBy(关键字)+属性名称(首字母要大写)+查询条件(首字母大写)。


public interface UsersRepositoryByName extends Repository<Users, Integer> {

    List<Users> findByName(String name);
    List<Users> findByNameAndAge(String name,Integer age);
    List<Users> findByNameLike(String name);
}
  • 测试类:
@SpringBootTest
public class ApplicationTest {

    @Autowired
    private Repositorys repositorys;

    @Test
    public void findUser() {
        List<Users> list = repositorys.findByusername("李四");
        for (Users user : list) {
            System.out.println(user);
        }
    }
}
  • 基于@Query注解的查询:

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

  • 创建接口:
public interface UserQuery extends Repository<Users,Integer> {

    @Query("from Users where username= :username")
    public List<Users> findByName(String username);

    @Query("from Users where username like %:username%")
    public List<Users> findLikeName(String username);

    @Query(value = "select *from users where username=?",nativeQuery = true)
    public List<Users> findByNameSQL(String username);

    @Query("update Users set username= :username where userid = :userid")
    @Modifying
    public void updateUser(String username,Integer userid);
}
  • 测试:
@SpringBootTest
public class TestQuery {

    @Autowired
    private UserQuery userQuery;

    @Test
    public void findByName() {
        List<Users> list = userQuery.findByName("李四");
        for (Users user:list) {
            System.out.println(user);
        }
    }
    @Test
    public void findLikeName(){
        List<Users> list = userQuery.findLikeName("李");
        for (Users user:list) {
            System.out.println(user);
        }
    }
    @Test
    public void findByNames(){
        List<Users> list = userQuery.findByNameSQL("李四");
        for (Users user:list) {
            System.out.println(user);
        }
    }

    @Test
    @Transactional
    @Rollback(false)
    public void updateUser(){
        this.userQuery.updateUser("王五",2);
    }
}

2.CrudRepository接口:

  • 创建接口:
public interface UserCrudRepository extends CrudRepository<Users,Integer> {
}
  • 测试:
@SpringBootTest
public class TestCrud {
    @Autowired
    private UserCrudRepository userCrudRepository;

    @Test
    public void saveUser() {
        Users users = new Users();
        users.setUsername("张三");
        users.setUserage(23);
        users.setAddress("上海");
        userCrudRepository.save(users);
    }
    @Test
    public void updateUser() {
        Users users = new Users();
        users.setUserid(3);
        users.setUsername("张小三");
        users.setAddress("郑州");
        users.setUserage(18);
    }
    @Test
    public void findOne() {
        Optional<Users> optianal = userCrudRepository.findById(3);
        Users users = optianal.get();
        System.out.println(users);
    }
    @Test
    public void findAll() {
        List<Users> list = (List<Users>) userCrudRepository.findAll();
        for (Users user : list) {
            System.out.println(user);
        }
    }
    @Test
    public void deleteUser() {
        userCrudRepository.deleteById(3);
    }
}

3.JpaRepository接口:

JpaRepository 接口是我们开发时使用的最多的接口。其特点是可以帮助我们将其他接口的方法的返回值做适配处理。可以使得我们在开发时更方便的使用这些方法。

  • 创建接口:
public interface UsersRepository extends JpaRepository<Users,Integer> {
}
  • 测试:
@SpringBootTest
class SpringdataJpaApplicationTests {

    @Autowired
    private UsersRepository usersRepository;

    //添加
    @Test
    public void addUser() {
        Users users = new Users();
        users.setUsername("张三");
        users.setUserage(18);
        users.setAddress("郑州");
        usersRepository.save(users);
    }
    //查询所有
    @Test
    public void findAll(){
        List<Users> list = usersRepository.findAll();
        for (Users user:list) {
            System.out.println(user);
        }
    }
    //ID查找
    @Test
    public void findById(){
        Optional<Users> optional = usersRepository.findById(1);
        Users users = optional.get();
        System.out.println(users);
    }
    //修改
    @Test
    public void updateUser(){
        Users users = new Users();
        users.setUserid(1);
        users.setUsername("李四");
        users.setUserage(20);
        users.setAddress("北京");
        usersRepository.save(users);
    }
    //删除
    @Test
    public void deleteUser(){
        usersRepository.deleteById(2);
    }
}

4.PagingAndSortingRepository接口

  • 创建接口:
public interface UserPageAndSort extends PagingAndSortingRepository<Users,Integer> {
}
  • 测试:
/**
 * 排序分页测试
 */
@SpringBootTest
public class TestPageAndSort {

    @Autowired
    private UserPageAndSort userPageAndSort;

    @Test
    public void TestSort(){
        //创建Order对象
        Sort.Order order =  Sort.Order.desc("userid");
        Sort sort = Sort.by(order);
        Iterable<Users> iterable = userPageAndSort.findAll(sort);
        for (Users user:iterable){
            System.out.println(user);
        }
    }

    @Test
    public void TestPage(){
        //Pageable:封装了分页的参数,当前页,每页显示的条数。当前页是从0开始。
        //PageRequest(page,size) page:当前页。size:每页显示的条数
//        Pageable pageable = new PageRequest(1,2); //低版本
        PageRequest pageRequest = PageRequest.of(0, 2);
        Page<Users> page = userPageAndSort.findAll(pageRequest);
        System.out.println("总条数:"+page.getTotalElements()+";总页数:"+page.getTotalPages());
        List<Users> list = page.getContent();
        for (Users user:list){
            System.out.println(user);
        }
    }

    @Test
    public void PageAndSort(){
        Sort.Order order= Sort.Order.desc("userid");
        Sort sort= Sort.by(order);
        PageRequest pageRequest = PageRequest.of(0,2,sort);

        Page<Users> page = userPageAndSort.findAll(pageRequest);
        System.out.println("总条数:"+page.getTotalElements()+";总页数:"+page.getTotalPages());
        List<Users> list = page.getContent();
        for (Users user:list) {
            System.out.println(user);
        }
    }
}

5.JpaSpecificationException接口:

JpaSpecificationExecutor接口主要提供了多条件查询的支持,并且可以在查询中添加分页与排序。
注意:JpaSpecificationExecutor接口
与以上接口没有关系,完全独立。不能单独使用,需要配合着 jpa 中的其他接口一起使用。

  • 创建接口:
public interface UserJpaSpecificationExecutor extends JpaSpecificationExecutor<Users>, JpaRepository<Users,Integer> {
}
  • 测试:
@SpringBootTest
public class TestJpaSpecificationExcutor {

    @Autowired
    private UserJpaSpecificationExecutor userJpaSpecificationExecutor;
    //单条件测试
    @Test
    public void TestJpaRepository(){
        //封装查询条件
        Specification<Users> specification = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.equal(root.get("username"), "张三");
                return predicate;
            }
        };
        List<Users> list = userJpaSpecificationExecutor.findAll(specification);
        for (Users user:list) {
            System.out.println(user);
        }
    }
    //多条件查询
    @Test
    public void TestJapSpecificationExecutor(){
        Specification<Users> specification = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                ArrayList<Predicate> list = new ArrayList<>();
                list.add(criteriaBuilder.equal(root.get("username"),"张三"));
                list.add(criteriaBuilder.equal(root.get("userage"),23));
                Predicate[] predicates = new Predicate[1];
                return criteriaBuilder.and(list.toArray(predicates));
            }
        };
        List<Users> list = userJpaSpecificationExecutor.findAll(specification);
        for (Users user:list){
            System.out.println(user);
        }
    }

    @Test
    public void testFindAll(){
        Specification<Users> specification = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                return criteriaBuilder.and(criteriaBuilder.like(root.get("username"),"%张%"),criteriaBuilder.ge(root.get("userage"),23));
            }
        };
        Sort.Order o = Sort.Order.desc("userage");
        Sort sort = Sort.by(o);
        PageRequest pageRequest = PageRequest.of(0, 2, sort);
        Page<Users> page = userJpaSpecificationExecutor.findAll(specification,pageRequest);
        System.out.println("总条数:"+page.getTotalElements()+";总页数"+page.getTotalPages());
        for (Users user:page){
            System.out.println(user);
        }
    }
}

二、关联查询

JPA定义了一个OneToMany关系,它与ManyToMany关系类似,但反向关系(如果已定义)是ManyToOne关系。 OneToMany与JPA中ManyToMany关系的主要区别在于,ManyToMany总是使用中间关系连接表来存储关系,OneToMany可以使用连接表或者目标对象的表引用中的外键源对象表的主键。

1.一对一关联查询:

需求:用户与身份的一对一的关联关系
用户:一方
身份证:一方

  • 创建用户:
@Entity
@Table
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int perid;
    @Column
    private String pername;

    public int getPerid() {
        return perid;
    }

    public void setPerid(int perid) {
        this.perid = perid;
    }

    public String getPername() {
        return pername;
    }

    public void setPername(String pername) {
        this.pername = pername;
    }
}
  • 创建IdCard:
@Entity
@Table
public class IdCard {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int cardid;
    @Column
    private String cardnum;

    //cascade代表级联操作
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "perid")
    private Person person;//一对一关系

    public int getCardid() {
        return cardid;
    }

    public void setCardid(int cardid) {
        this.cardid = cardid;
    }

    public String getCardnum() {
        return cardnum;
    }

    public void setCardnum(String cardnum) {
        this.cardnum = cardnum;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}
  • 创建接口:
public interface PersonJpaRepository extends JpaRepository<IdCard,Integer> {
}
  • 测试:
@SpringBootTest
public class TestPerson {

    @Autowired
    private PersonJpaRepository personJpaRepository;

    @Test
    public void testAdd() {
        Person person = new Person();
        person.setPername("张三");
        IdCard idCard = new IdCard();
        idCard.setCardnum("412722199910101234");
        idCard.setPerson(person);
        personJpaRepository.save(idCard);
    }

    @Test
    public void testFindAll(){
        List<IdCard> list = personJpaRepository.findAll();
        for (IdCard idcard:list) {
            System.out.println(idcard);
        }
    }
}

2.一对多关联查询:

需求:从员工和部门的一对多的关联关系
部门:一方
员工:多方

一对多的数据库模型
  • 创建员工实体:
@Entity
@Table
public class Emp {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int empid;
    @Column
    private String empname;

    @ManyToOne(cascade = CascadeType.PERSIST)//多对一关系
    @JoinColumn(name = "deptid")
    private Dept dept;

    public int getEmpid() {
        return empid;
    }

    public void setEmpid(int empid) {
        this.empid = empid;
    }

    public String getEmpname() {
        return empname;
    }

    public void setEmpname(String empname) {
        this.empname = empname;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }
}
  • 创建部门实体:
@Entity
@Table
public class Dept {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int deptid;
    @Column
    private String deptname;

    @OneToMany(mappedBy = "dept")//mappedBy用于指定关系维护
    private Set<Emp> emp=new HashSet<>();

    public int getDeptid() {
        return deptid;
    }

    public void setDeptid(int deptid) {
        this.deptid = deptid;
    }

    public String getDeptname() {
        return deptname;
    }

    public void setDeptname(String deptname) {
        this.deptname = deptname;
    }

    public Set<Emp> getEmp() {
        return emp;
    }

    public void setEmp(Set<Emp> emp) {
        this.emp = emp;
    }
}
  • 创建接口:
public interface EmpJpaRepository extends JpaRepository<Emp,Integer> {
}
  • 测试:
@SpringBootTest
public class TestEmp {
    @Autowired
    private EmpJpaRepository empJpaRepository;

    @Test
    public void TestAdd(){
        Dept dept = new Dept();
        dept.setDeptname("人事部");
        Emp emp = new Emp();
        emp.setEmpname("Admin");
        emp.setDept(dept);
        empJpaRepository.save(emp);
    }
    @Test
    public void testFindAll(){
        List<Emp> list = empJpaRepository.findAll();
        for (Emp emp:list){
            System.out.println(emp);
        }
    }
}
sql语句

3.多对多关联查询:

需求:一个学生可以拥有多个课程,一个课程可以分配多个学生。
多对多的关联关系
学生:多方
课程:多方

  • 创建学生实体:


    多对多数据库模型
@Entity
@Table
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int stuid;
    @Column
    private String stuname;
    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "stu_cou",joinColumns = @JoinColumn(name = "stuid"),
            inverseJoinColumns = @JoinColumn(name = "couid"))
    private Set<Course> course = new HashSet<>();

    public int getStuid() {
        return stuid;
    }

    public void setStuid(int stuid) {
        this.stuid = stuid;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public Set<Course> getCourse() {
        return course;
    }

    public void setCourse(Set<Course> course) {
        this.course = course;
    }
}
  • 创建课程实体:
@Entity
@Table
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int couid;
    @Column
    private String couname;
    //维护关系,mappedBy=“对方和当前对象关联的对象名称”
    @ManyToMany(mappedBy = "course")
    private Set<Student> students = new HashSet<>();

    public int getCouid() {
        return couid;
    }

    public void setCouid(int couid) {
        this.couid = couid;
    }

    public String getCouname() {
        return couname;
    }

    public void setCouname(String couname) {
        this.couname = couname;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}
  • 创建接口:
public interface StudentJpaRepository extends JpaRepository<Student,Integer> {
}
  • 测试:
@SpringBootTest
public class TestStudent {

    @Autowired
    StudentJpaRepository studentJpaRepository;

    @Test
    public void testAdd(){
        Student student = new Student();
        student.setStuname("张三");
        Course course = new Course();
        course.setCouname("Java");
        Course course1 = new Course();
        course1.setCouname("C++");
        student.getCourse().add(course);
        student.getCourse().add(course1);
        studentJpaRepository.save(student);
    }
}

4.使用的注解:

(1)@JoinTable:配置中间表信息;
joinColumns:建立当前表在中间表中的外键字段;
(2)一对一:@OneToOne;
一对多:@OneToMany;
多对一:@ManyToOne;
多对多:@ManyToMany;
(3)@Table:声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe);
(4)@GeneratedValue(strategy=GenerationType.IDENTITY):注解存在的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键);

  • mappedBy 属性:

mappedBy是OneToOne、OneToMany和ManyToMany这三种关联关系的属性。用来标注拥有这种关系的字段。 除非关系是单向的,否则是必需的。那么什么叫拥有关联关系呢,假设是双向一对一的话,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力。而另一方没有,只能被动管理。由于JoinTable和JoinColumn一般定义在拥有关系的这一端,而mappedBy一定是定义在关系的被拥有方(the owned side),也就是跟定义JoinTable和JoinColumn互斥的一方,它的值指向拥有方中关于被拥有方的字段,可能是一个对象(OneToMany),也可能是一个对象集合(ManyToMany)。

  • 级联关系类型:

(1)CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法。
(2)CascadeType.REMOVE:级联删除,当调用remove()方法删除Order实体时会先级联删除OrderItem的相关数据。
(3)CascadeType.MERGE:级联更新,当调用了Merge()方法,如果Order中的数据改变了会相应的更新OrderItem中的数据。
(4)CascadeType.ALL:包含以上所有级联属性。
(5)CascadeType.PERSIST:级联保存,当调用了Persist() 方法,会级联保存相应的数据。

相关文章

网友评论

    本文标题:Spring Data学习day93:Spring Data J

    本文链接:https://www.haomeiwen.com/subject/jfjiwctx.html