美文网首页
记录SpringDataJpa学习

记录SpringDataJpa学习

作者: ccccaixiaohao | 来源:发表于2020-04-14 22:09 被阅读0次

    参考博客:https://blog.csdn.net/phapha1996/article/details/83614975

    1.环境搭建

    pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>test</groupId>
      <artifactId>springDataJpa</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <name>springDataJpa</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <!-- 引入springboot parent-->
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
      </parent>
    
      <dependencies>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
          <exclusions>
            <exclusion>
              <groupId>org.junit.vintage</groupId>
              <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
    
        <!--mysql依赖-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.11</version>
        </dependency>
    
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
    
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.4</version>
          <scope>provided</scope>
        </dependency>
    
      </dependencies>
    
    </project>
    

    2.Entity和Dao编写

    1.声明实体对应的表和表字段

    package com.cwh.Entity;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "t_car")
    public class Car {
    
        @Id
        @Column(name = "id")
        private String id;
    
        @Column(name = "name")
        private String name;
    
        @Column(name = "power")
        private String power;
    
        @ManyToOne(targetEntity = Person.class)
        @JoinColumn(name = "owner",referencedColumnName = "id")
        private Person person;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPower() {
            return power;
        }
    
        public void setPower(String power) {
            this.power = power;
        }
    
        public Person getPerson() {
            return person;
        }
    
        public void setPerson(Person person) {
            this.person = person;
        }
    
    }
    

    4.编写dao

    继承jpa的两个接口

    public interface CarDao extends JpaRepository<Car,String>, JpaSpecificationExecutor<Car> {
    }
    

    3.使用JPA进行持久操作

    JPA操作有四种方式:
    1.JPA接口中的方法
    2.编写JPQL语句
    3.编写SQL语句
    4.按照函数命名规则进行接口名称编写

    1.方式一:JPA接口中的方法

    /**
     * 方式一:通过repository的内置方法
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootApplication.class)
    public class PersonDaoTest {
    
        @Resource
        private PersonDao personDao;
    
        @Test
        public void queryByAll(){
            List<Person> all = personDao.findAll();
            for (Person item : all){
                System.out.println(item);
            }
        }
    
        @Test
        public void save(){
            Person test = new Person();
            test.setId("2222");
            test.setAddress("zh");
            Person save = personDao.save(test);
            System.out.println(save);
        }
    
        @Test
        public void delete(){
            Person test = new Person();
            test.setId("1");
            personDao.delete(test);
        }
    
    }
    

    2.方式二:编写JPQL语句

    DAO:

    @Query(value = "from Person")
        public List<Person> JpqlFindAll();
    
        @Query(value = "from Person where name = ?1")
        public Person JpqlFindByName(String name);
    
        @Query(value = "update Person set age =?2 where name = ?1")
        @Modifying
        public int JpaqlUpdateAgeByName(String name,int age);
    

    测试类:

    /**
     * 方式二:采用jpql
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootApplication.class)
    public class PersonDaoTest2 {
    
        @Resource
        private PersonDao personDao;
    
        @Test
        public void TestFindAll(){
            List<Person> people = personDao.JpqlFindAll();
            for (Person item: people) {
                System.out.println(item);
            }
        }
    
        @Test
        public void TestFindByName(){
            Person person = personDao.JpqlFindByName("test");
            System.out.println(person);
        }
    
        @Test
        @Transactional
        @Rollback(value = false)
        public void updateAgeByName(){
            System.out.println(personDao.JpaqlUpdateAgeByName("test",20));
        }
    
    }
    

    3.方式三:编写SQL语句

    DAO:

    @Query(value = "select * from t_personal",nativeQuery = true)
        public List<Person> sqlFindAll();
    
        @Query(value = "select * from t_personal where name = ?1",nativeQuery = true)
        public Person sqlFindByName(String name);
    
        @Query(value = "update t_personal set age =?2 where name=?1",nativeQuery = true)
        @Modifying
        public void sqlUpdateAgeByName(String name,int age);
    

    测试类:

    /**
     * 方式三:采用sql
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootApplication.class)
    public class PersonDaoTest3 {
    
        @Resource
        private PersonDao personDao;
    
        @Test
        public void TestFindAll(){
            List<Person> people = personDao.sqlFindAll();
            for (Person item: people) {
                System.out.println(item);
            }
        }
    
        @Test
        public void TestFindByName(){
            Person person = personDao.sqlFindByName("test2");
            System.out.println(person);
        }
    
        @Test
        @Transactional
        @Rollback(value = false)
        public void TestUpdate(){
            personDao.sqlUpdateAgeByName("test2",99);
        }
    }
    

    4.方式四:使用规定命名的方式

    DAO:

    public Person findByName(String name);
    
    public List<Person> findByNameLike(String name);
    
    public Person findByNameAndAge(String name,int age);
    

    测试类:

    /**
     * 方式四:采用函数名定义
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootApplication.class)
    public class PersonDaoTest4 {
    
        @Autowired
        private PersonDao personDao;
    
        @Test
        public void TestFindByName(){
            Person person = personDao.findByName("test");
            System.out.println(person);
        }
    
        @Test
        public void TestFindByNameList(){
            List<Person> byNameLike = personDao.findByNameLike("test%");
            for (Person item:byNameLike){
                System.out.println(item);
            }
        }
    
        @Test
        public void TestFindByNameAndAge(){
            Person person = personDao.findByNameAndAge("test2",99);
            System.out.println(person);
    
        }
    }
    

    4.JPA多表操作

    1.一对多

    一方实体类:
    常规:

    @OneToMany(targetEntity = Car.class)
     @JoinColumn(name = "owner",referencedColumnName = "id")
    private Set<Car> cars = new HashSet<>();
    

    放弃维护,级联方式:

    @OneToMany(mappedBy = "person",cascade = CascadeType.ALL)   //一方维护,级联方式
    private Set<Car> cars = new HashSet<>();
    

    放弃维护,级联方式,立即加载:

    @OneToMany(mappedBy = "person",cascade = CascadeType.ALL,fetch = FetchType.EAGER) //立即加载
        private Set<Car> cars = new HashSet<>();
    

    多方实体类:
    onwer为外键,id为person表主键

     @ManyToOne(targetEntity = Person.class)
     @JoinColumn(name = "owner",referencedColumnName = "id")
        private Person person;
    

    2.多对多

    多方实体类:
    JoinTable name中间表的名称,joinColumns 本实体,inverseJoinColumns 对方实体
    referencedColumnName 中间表字段名称

    @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
        @JoinTable(
                name = "t_person_role",
                joinColumns = {@JoinColumn(name = "personal_id",referencedColumnName = "id")},
                inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}
        )
    

    对方实体类:
    mappedBy放弃维权

    //    @ManyToMany(targetEntity = Role.class)
    //    @JoinTable(
    //            name = "t_person_role",
    //            joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")},
    //            inverseJoinColumns = {@JoinColumn(name = "personal_id",referencedColumnName = "id")}
    //    )
        @ManyToMany(mappedBy = "roles") //放弃维权
        private Set<Person> persons = new HashSet<>();
    

    5.自定义查询

    1.使用JPQL自定义查询

    DAO:

    @Query(value = "select new com.cwh.Vo.PersonVo(p.name,p.age) from Person p where p.name like :name")
        public List<PersonVo> getNameAndAgeList(@Param("name") String name);
    

    接受类:
    需要一一对应查询出来的字段

    @Data
    public class PersonVo {
        private String name;
        private Integer age;
    
        public PersonVo(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }
    

    测试类:

        @Test
        public void getNameAndAgeList(){
            List<PersonVo> persons = personDao.getNameAndAgeList("%11%");
            for (PersonVo item : persons){
                System.out.println(item);
            }
    
        }
    

    2.使用SQL自定义查询

    DAO:
    需使用MAP或OBJECT去接收

    @Query(value = "select p.name as name,c.name as carName from t_personal p left join t_car c on p.id = c.owner",nativeQuery = true)
        public List<Map<String,Object>> getPersonAndCar();
    

    测试类:

    @Test
        public void getPersonAndCar(){
            List<Map<String,Object>> persons = personDao.getPersonAndCar();
            for (Map<String,Object> item : persons){
                System.out.println(item.get("carName"));
            }
        }
    

    6.导航查询

    需要在配置了一对多和多对多基础上
    测试类:

    @Test
        @Transactional
        public void testQuery(){
            Optional<Person> byId = personDao.findById("4444");
            Person person = byId.get();
            Set<Car> cars = person.getCars();
            for (Car car:cars) {
                System.out.println(car);
            }
        }
    

    6.Querydsl使用

    官方文档:http://www.querydsl.com/static/querydsl/4.1.3/reference/html_single/

    1.导入依赖

    <!--queryDsl-->
        <dependency>
          <groupId>com.querydsl</groupId>
          <artifactId>querydsl-apt</artifactId>
          <version>${querydsl.version}</version>
        </dependency>
    
        <dependency>
          <groupId>com.querydsl</groupId>
          <artifactId>querydsl-jpa</artifactId>
          <version>${querydsl.version}</version>
        </dependency>
    

    2.操作

    1.查询实体类,可以直接用实体类去接收

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootApplication.class)
    public class QdslTest {
        @Resource
        private EntityManager entityManager;
    
        private JPAQueryFactory jpaQueryFactory;
    
        @PostConstruct
        public void initFactory(){
            jpaQueryFactory = new JPAQueryFactory(entityManager);
        }
    
        @Test
        public void testQueryAll(){
            QPerson qPerson = QPerson.person;
            List<Person> persons = jpaQueryFactory.select(qPerson)
                    .from(qPerson)
                    .fetch();
            for (Person item:persons) {
                System.out.println(item);
            }
        }
    
    }
    

    2.查询自定义字段,返回值需要自己再去处理

    @Test
        public void testQuery(){
            QPerson qPerson = QPerson.person;
            List<Tuple> fetch = jpaQueryFactory.select(qPerson.name, qPerson.age)
                    .from(qPerson).fetch();
    
            for (Tuple item:fetch) {
                System.out.println(item.get(qPerson.name));
                System.out.println(item.get(qPerson.age));
            }
        }
    

    3.左连接查询

    @Test
        public void testLeftQuery(){
            QPerson qPerson = QPerson.person;
            QCar qCar = QCar.car;
            List<Tuple> fetch = jpaQueryFactory.select(qPerson, qCar)
                    .from(qPerson)
                    .leftJoin(qCar)
                    .on(qPerson.id.eq(qCar.person.id))
                    .fetch();
            for (Tuple item:fetch) {
                System.out.println(item.get(qCar));
            }
        }
    

    4.使用指定类去接收放回参数

    @Test
        public void testQueryWithDto(){
            QPerson qPerson = QPerson.person;
            List<PersonVo> personVos = jpaQueryFactory.select(Projections.constructor(PersonVo.class, qPerson.name, qPerson.age))
                    .from(qPerson)
                    .fetch();
            for (PersonVo item:personVos) {
                System.out.println(item);
            }
        }
    

    5.分组查询

    @Test
        public void testGroupQuery(){
            QPerson qPerson = QPerson.person;
            List<Tuple> fetch = jpaQueryFactory.select(qPerson.name ,qPerson.name.count())
                    .from(qPerson)
                    .groupBy(qPerson.name)
                    .fetch();
            for (Tuple item:fetch) {
                System.out.println(item.get(qPerson.name.count()));
            }
        }
    

    相关文章

      网友评论

          本文标题:记录SpringDataJpa学习

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