站保站

服务市场
  • 网站市场
  • 单机游戏
  • 平台大厅
  • 转让市场
  • 发卡市场
  • 广告市场
  • 下载市场
  • 收录市场
  • 本站平台
    平台客服
    微信Q群



    平台微博/weibo    平台微信/公众号    平台抖音/快手   
    曝光台    保障    地图   
    上传资源 快速赚钱
    站保站    登录      |  注册  |  

    只需一步,快速开始!

     找回密码   |   协议
    热门搜索: 网站开发 App报毒 挖矿源码 代办资质

    Spring Data Jpa总结--查询方式、多表关系

    • 时间:2020-10-26 16:04 编辑:那股哇 来源: 阅读:64
    • 扫一扫,手机访问
    摘要:

    Spring Data Jpa基本说明

    操作步骤

    1. 创建实体类,建立与数据表的关联
    2. 编写一个符合Jpa规范的Dao层接口
    3. 完成CRUD操作

    接口说明

    • JpaRepository<实体类类型, 主键类型>:接口中封装了一些基本的增删查改方法

    在这里插入图片描述

    • JpaSpecificationExecutor<实体类类型>:完成一些复杂操作,如分页查询,可完成动态查询,即自定义查询条件

      @Test
      public void testSpec(){//查询
      
          //自定义查询条件
          Specification<Customer> spec = new Specification<Customer>() {
              @Override
              public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                  //1. 获取比较的属性
                  Path custName = root.get("custName");
                  //2. 构造查询条件
                  Predicate predicate = criteriaBuilder.equal(custName, "zhangsan");
                  return predicate;
              }
          };
      
          Customer customer = customerDao.findOne(spec);
          System.out.println(customer);
      }
      
      @Test
      public void testLike(){//模糊查询
          Specification<Customer> spec = new Specification<Customer>() {
              @Override
              public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                  Path custName = root.get("custName");
                  Predicate like = criteriaBuilder.like(custName.as(String.class), "zhang%");
                  return like;
              }
          };
          Sort sort = new Sort(Sort.Direction.DESC, "custId");
          List<Customer> customers = customerDao.findAll(spec, sort);
          for (Customer customer : customers) {
              System.out.println(customer);
          }
      }
      
      
      @Test
      public void testPage(){//分页
          Specification spec = null;
          Pageable pageable = new PageRequest(0, 2);//(页码,每页条数)
          Page<Customer> customers = customerDao.findAll(pageable);
          for (Customer customer : customers) {
              System.out.println(customer);
          }
      
          System.out.println(customers.getTotalElements());
          System.out.println(customers.getTotalPages());
          System.out.println(customers.getContent());
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50

    开发环境搭建

    导入maven依赖

    <properties>
        <spring.version>4.2.4.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>
    
    <dependencies>
        <!-- junit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    
        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <!-- spring end -->
    
        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->
    
        <!-- c3p0 beg -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>
        <!-- c3p0 end -->
    
        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->
    
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <!-- el beg 使用spring data jpa 必须引入 -->
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>2.2.4</version>
        </dependency>
    
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.4</version>
        </dependency>
        <!-- el end -->
    </dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142

    配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
           xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    		http://www.springframework.org/schema/data/jpa
    		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    
        <!--spring 和 spring data jpa 的配置-->
        <!--1. 创建entityManagerFactory对象交给spring容器管理-->
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!--配置扫描的包(实体类所在包)-->
            <property name="packagesToScan" value="cn.itcast.domain"/>
            <!--jpa实现厂家-->
            <property name="persistenceProvider">
                <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
            </property>
    
            <!--jpa供应商适配器-->
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <!--是否自动创建数据表-->
                    <property name="generateDdl" value="false" />
                    <!--数据库类型-->
                    <property name="database" value="MYSQL" />
                    <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
                    <!--是否显示SQL-->
                    <property name="showSql" value="true" />
                </bean>
            </property>
    
            <property name="jpaDialect">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
            </property>
    
            <!--注入jpa的配置信息
                auto:自动创建数据库
                create:每次重新创建数据库
                update:有表不会重新创新
            -->
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                </props>
            </property>
        </bean>
    
        <!--2. 创建数据库连接池-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="root"/>
            <property name="password" value="password"/>
            <property name="driverClass" value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql:///jpa"/>
        </bean>
    
        <!--3. 整合spring data jpa-->
        <jpa:repositories base-package="cn.itcast.dao" transaction-manager-ref="transactionManager"
                          entity-manager-factory-ref="entityManagerFactory"/>
    
        <!--4. 配置事务管理器-->
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
        </bean>
    
        <!--5. 配置包扫描-->
        <context:component-scan base-package="cn.itcast"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    创建实体类

    @Entity //声明实体类
    @Table(name="cst_customer") //建立实体类和表的映射关系
    public class Customer {
        
        @Id//声明当前私有属性为主键
        @GeneratedValue(strategy=GenerationType.IDENTITY) //配置主键的生成策略
        @Column(name="cust_id") //指定和表中cust_id字段的映射关系
        private Long custId;
        
        @Column(name="cust_name") //指定和表中cust_name字段的映射关系
        private String custName;
        
        @Column(name="cust_source")//指定和表中cust_source字段的映射关系
        private String custSource;
    	......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Spring Data Jpa的查询方式

    • 除了使用JpaRepository等接口中定义好的方法查询外,还有以下几个查询方法

    JPQL方式查询

    public interface CustomerDao extends JpaRepository<Customer, Long>,JpaSpecificationExecutor<Customer> {    
        //@Query 使用jpql的方式查询。
        @Query(value="from Customer")
        public List<Customer> findAllCustomer();
        
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
        @Query(value="from Customer where custName = ?1")
        public Customer findCustomer(String custName);
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying//@Modifying 来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询
        public void updateCustomer(String custName,Long custId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    本地SQL查询

    /**
         * nativeQuery : 使用本地sql的方式查询
         */
    @Query(value="select * from cst_customer",nativeQuery=true)
    public void findSql();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方法命名规则查询

    • 按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。
    //方法命名方式查询(根据客户名称查询客户)
    public Customer findByCustName(String custName);
    
    • 1
    • 2
    KeywordSampleJPQL snippet
    AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
    OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
    Is, EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
    BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
    LessThanfindByAgeLessThan… where x.age < ?1
    LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
    GreaterThanfindByAgeGreaterThan… where x.age > ?1
    GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
    AfterfindByStartDateAfter… where x.startDate > ?1
    BeforefindByStartDateBefore… where x.startDate < ?1
    IsNull, NullfindByAge(Is)Null… where x.age is null
    IsNotNull, NotNullfindByAge(Is)NotNull… where x.age not null
    LikefindByFirstnameLike… where x.firstname like ?1
    NotLikefindByFirstnameNotLike… where x.firstname not like ?1
    StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
    EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
    ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
    OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
    NotfindByLastnameNot… where x.lastname <> ?1
    InfindByAgeIn(Collection<Age> ages)… where x.age in ?1
    NotInfindByAgeNotIn(Collection<Age> ages)… where x.age not in ?1
    TruefindByActiveTrue()… where x.active = true
    FalsefindByActiveFalse()… where x.active = false
    IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

    多表设计

    Jpa中的一对多

    • 在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表。在数据库中建立一对多的关系,需要使用数据库的外键约束。

    • 外键:指的是从表中有一列,取值参照主表的主键
      在这里插入图片描述

    • 实体类关系的建立以及映射配置

      //配置客户和联系人的一对多关系,一个客户可以有多个联系人
      @OneToMany(targetEntity=LinkMan.class)
      @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
      private Set<LinkMan> linkmans = new HashSet<>();
      //getter、setter
      
      • 1
      • 2
      • 3
      • 4
      • 5
      //多对一关系映射:多个联系人对应客户
      @ManyToOne(targetEntity=Customer.class)
      @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
      private Customer customer;//用它的主键,对应联系人表中的外键
      //getter、setter
      
      • 1
      • 2
      • 3
      • 4
      • 5

      当建立了双向的关联关系后,先保存主表,再保存从表,会产生2条insert和1条update,而实际开发中我们只需要2条insert。

      解决方法就是"一"的一方放弃维护权。

      @OneToMany(mappedBy="customer")
      
      • 1
    • 映射的注解说明

      @OneToMany:

      作用:建立一对多的关系映射

      属性:

      ​ targetEntityClass:指定多的多方的类的字节码

      ​ mappedBy:指定从表实体类中引用主表对象的名称。

      ​ cascade:指定要使用的级联操作

      ​ fetch:指定是否采用延迟加载

      ​ orphanRemoval:是否使用孤儿删除

      @ManyToOne

      作用:建立多对一的关系

      属性:

      ​ targetEntityClass:指定一的一方实体类字节码

      ​ cascade:指定要使用的级联操作

      ​ fetch:指定是否采用延迟加载

      ​ optional:关联是否可选。如果设置为false,则必须始终存在非空关系。

      @JoinColumn

      作用:用于定义主键字段和外键字段的对应关系。

      属性:

      ​ name:指定外键字段的名称

      ​ referencedColumnName:指定引用主表的主键字段名称

      ​ unique:是否唯一。默认值不唯一

      ​ nullable:是否允许为空。默认值允许。

      ​ insertable:是否允许插入。默认值允许。

      ​ updatable:是否允许更新。默认值允许。

      ​ columnDefinition:列的定义信息。

    Jpa中的多对多

    • 多对多的表关系建立靠的是中间表,其中用户表和中间表的关系是一对多,角色表和中间表的关系也是一对多
      在这里插入图片描述

    • 实体类关系的建立以及映射配置

      //多对多关系映射
      //在Role类中添加
      @ManyToMany
      @JoinTable(name="user_role_rel",//中间表的名称
                 //中间表user_role_rel字段关联sys_role表的主键字段role_id
                 joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},
                 //中间表user_role_rel的字段关联sys_user表的主键user_id
                 inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}
                )
      private Set<SysUser> users = new HashSet<>();
      
      //在被动的一方要放弃维护权,避免保存中存在主键冲突的问题
      //User类
      @ManyToMany(mappedBy="users")
      private Set<SysRole> roles = new HashSet<>();
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 注解说明

      @ManyToMany

      ​ 作用:用于映射多对多关系

      ​ 属性:

      ​ cascade:配置级联操作。

      ​ fetch:配置是否采用延迟加载。从一方查多方,默认延迟加载;从多方查一方,默认立即加载

      ​ targetEntity:配置目标的实体类。映射多对多的时候不用写。

      @JoinTable

      作用:针对中间表的配置

      属性:

      ​ nam:配置中间表的名称

      ​ joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段

      ​ inverseJoinColumn:中间表的外键字段关联对方表的主键字段

      @JoinColumn

      作用:用于定义主键字段和外键字段的对应关系。

      属性:

      ​ name:指定外键字段的名称

      ​ referencedColumnName:指定引用主表的主键字段名称

      ​ unique:是否唯一。默认值不唯一

      ​ nullable:是否允许为空。默认值允许。

      ​ insertable:是否允许插入。默认值允许。

      ​ updatable:是否允许更新。默认值允许。

      ​ columnDefinition:列的定义信息。

    • 全部评论(0)
    • 最新

    信息加载中,请等待

    微信客服(速回)

    微信客服(慢回)



    企业微信客服二维码
    联系我们
    平台客服: 平台QQ客服

    平台电话:400电话迁移中!

    平台邮箱:28292383@qq.com

    工作时间:周一至周五:早10:00 晚:18:00

    营业执照     网站ICP备案:鲁ICP备20027607号-1     鲁公网安备:37068702000078号     增值电信业务经营许可证、在线数据与交易处理业务许可证:鲁B2-20200681      © 2016-2024 站保站  https://www.zhanbaozhan.com/ 版权所有!      平台规范:   关于我们   广告合作   隐私条款   免责声明   法律声明   服务条款   网站地图   平台工单!