zoukankan      html  css  js  c++  java
  • SpringDataJpa基础知识

    一、Spring Data JPA 为此提供了一些表达条件查询的关键字

     1 And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
     2 Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
     3 Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
     4 LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
     5 GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
     6 IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
     7 IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
     8 NotNull --- 与 IsNotNull 等价;
     9 Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
    10 NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
    11 OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
    12 Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
    13 In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
    14 NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

    二、使用 @Query 创建查询

    @Query 注解的使用非常简单,只需在声明的方法上面标注该注解,同时提供一个 JP QL 查询语句即可,如下所示:

    1 public interface UserDao extends Repository<AccountInfo, Long> { 
    2  
    3 @Query("select a from AccountInfo a where a.accountId = ?1") 
    4 public AccountInfo findByAccountId(Long accountId); 
    5  
    6    @Query("select a from AccountInfo a where a.balance > ?1") 
    7 public Page<AccountInfo> findByBalanceGreaterThan( 
    8 Integer balance,Pageable pageable); 
    9 }

    很多开发者在创建 JP QL 时喜欢使用命名参数来代替位置编号,@Query 也对此提供了支持。JP QL 语句中通过": 变量"的格式来指定参数,同时在方法的参数前面使用 @Param 将方法参数与 JP QL 中的命名参数对应,示例如下:

     1 public interface UserDao extends Repository<AccountInfo, Long> { 
     2  
     3 public AccountInfo save(AccountInfo accountInfo); 
     4  
     5 @Query("from AccountInfo a where a.accountId = :id") 
     6 public AccountInfo findByAccountId(@Param("id")Long accountId); 
     7  
     8   @Query("from AccountInfo a where a.balance > :balance") 
     9   public Page<AccountInfo> findByBalanceGreaterThan( 
    10 @Param("balance")Integer balance,Pageable pageable); 
    11 }

    此外,开发者也可以通过使用 @Query 来执行一个更新操作,为此,我们需要在使用 @Query 的同时,用 @Modifying 来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询。如下所示:

    1 @Modifying 
    2 @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") 
    3 public int increaseSalary(int after, int before);

    三、SpringData-懒加载的作用和应用场景

    预期:
         启用懒加载后,对Student表取数,不会自动带出Course集合
         当student1.getCourse()使用集合时,再执行Student取数
    作用:
         当不需要使用Course集合引用时,不会执行多余的查询,提升效率
    

    四、springdataJpa复杂查询

    package bidding.model.specification;
    
    
    import bidding.model.dto.BiddingSupplierOrderManagerModelDto;
    import bidding.model.po.JcbdBdProvider;
    import bidding.model.po.JcbdBidding;
    import bidding.model.po.JcbdBiddingOrderItem;
    import bidding.model.po.JcbdMallOrder;
    import lombok.Data;
    import org.springframework.data.jpa.domain.Specification;
    import utils.Lang;
    import utils.string.StringUtils;
    
    import javax.persistence.criteria.*;
    import java.util.ArrayList;
    import java.util.List;
    /**
    * @date 2018/4/14
    */
    @Data
    public class BiddingSupplierOrderManagerSpecification<T> implements Specification<T>{
    
        private BiddingSupplierOrderManagerModelDto biddingSupplierOrderManagerModelDto;
    
        public BiddingSupplierOrderManagerSpecification() {
        }
    
        public BiddingSupplierOrderManagerSpecification(BiddingSupplierOrderManagerModelDto biddingSupplierOrderManagerModelDto) {
            this.biddingSupplierOrderManagerModelDto = biddingSupplierOrderManagerModelDto;
        }
    
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(cb.equal(root.get("isDelete"), false));
            predicates.add(cb.isNotNull(root.get("supplierOrderStatus")));
            if (!StringUtils.isEmpty(biddingSupplierOrderManagerModelDto.getProviderId()) && !biddingSupplierOrderManagerModelDto.getProviderId().isEmpty()) {
                predicates.add(cb.equal(root.get("providerId"), biddingSupplierOrderManagerModelDto.getProviderId()));
            }
            if (!StringUtils.isEmpty(biddingSupplierOrderManagerModelDto.getBiddingCode()) && !biddingSupplierOrderManagerModelDto.getBiddingCode().isEmpty()) {
                predicates.add(cb.equal(root.get("jcbdOrder").get("jcbdBidding").get("biddingCode"), biddingSupplierOrderManagerModelDto.getBiddingCode()));
            }
            if (!StringUtils.isEmpty(biddingSupplierOrderManagerModelDto.getGoodsCode()) && !biddingSupplierOrderManagerModelDto.getGoodsCode().isEmpty()) {
                Join<JcbdMallOrder, JcbdBiddingOrderItem> biddingJoin = root.join("jcbdBiddingOrderItems",JoinType.INNER);
                predicates.add(cb.equal(biddingJoin.get("sku"), biddingSupplierOrderManagerModelDto.getGoodsCode()));
            }
            if (!Lang.isEmpty(biddingSupplierOrderManagerModelDto.getStatus())) {
                predicates.add(cb.equal(root.get("supplierOrderStatus"), biddingSupplierOrderManagerModelDto.getStatus()));
            }
            if (biddingSupplierOrderManagerModelDto.getOrderStartTime() != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("dateCreated"), biddingSupplierOrderManagerModelDto.getOrderStartTime()));
            }
            if (biddingSupplierOrderManagerModelDto.getOrderEndTime() != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("dateCreated"), biddingSupplierOrderManagerModelDto.getOrderEndTime()));
            }
    
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }
    }
    package bidding.model.po;
    
    import bidding.model.po.base.BaseDomain;
    import com.alibaba.fastjson.annotation.JSONField;
    import org.hibernate.annotations.GenericGenerator;
    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @version 0.9 竞价采购实物商城订单表 2018-3-7 14:31:21.
     */
    
    @Entity
    public class JcbdMallOrder extends BaseDomain implements Serializable {
    
        /**
         * 主键.
         */
        @Id
        @GenericGenerator(name = "PKUUID", strategy = "uuid2")
        @GeneratedValue(generator = "PKUUID")
        private String id;
    
        /**
         * 竞价id.
         */
        @ManyToOne
        @JoinColumn(name = "JCBD_ORDER_ID", foreignKey = @ForeignKey(name = "FK_BIDDING_MALL_ORDER"))
        private JcbdOrder jcbdOrder;
    
        @OneToMany(mappedBy = "jcbdMallOrder",fetch = FetchType.LAZY,cascade = CascadeType.ALL)
        List<JcbdBiddingOrderItem> jcbdBiddingOrderItems;   ..........
    }package bidding.model.po;import bidding.model.po.base.BaseDomain;
    import org.hibernate.annotations.GenericGenerator;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToOne;
    
    /**
     * 竞价订单商品项表
     *
     * @author torvalds on 2018/4/24 21:36.
     * @version 1.0
     */
    @Entity
    public class JcbdBiddingOrderItem extends BaseDomain {
        /**
         * 主键.
         */
        @Id
        @GenericGenerator(name = "PKUUID", strategy = "uuid2")
        @GeneratedValue(generator = "PKUUID")
        private String id;
    @ManyToOne
    private JcbdMallOrder jcbdMallOrder;
    private String sku;
    .......... }

     五、JPA注解介绍

    JPA 注解的几个要点 

    1.设置Pojo为实体 

    1 @Entity //标识这个pojo是一个jpa实体     
    2 public class Users implements Serializable {     
    3 }    

    2.设置表名

    1 @Entity     
    2 @Table(name = "users") //指定表名为users     
    3 public class Users implements Serializable {     
    4 }    

    3.设置主键

    1 public class Users implements Serializable {     
    2 @Id     
    3 private String userCode;    

    4. 设置字段类型 

     1 通过@Column注解设置,包含的设置如下 
     2 name:字段名 
     3 unique:是否唯一 
     4 nullable:是否可以为空 
     5 inserttable:是否可以插入 
     6 updateable:是否可以更新 
     7 columnDefinition: 定义建表时创建此列的DDL 
     8 secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。 
     9 
    10 @Column(name = "user_code", nullable = false, length=32)//设置属性userCode对应的字段为user_code,长度为32,非空     
    11 private String userCode;     
    12 @Column(name = "user_wages", nullable = true, precision=12, scale=2)//设置属性wages对应的字段为user_wages,12位数字可保留两位小数,可以为空     
    13 private double wages;     
    14 @Temporal(TemporalType.DATE)//设置为时间类型     
    15 private Date joinDate;    

    5.字段排序

    在加载数据的时候可以为其指定顺序,使用@OrderBy注解实现 

    1 @Table(name = "USERS")     
    2 public class User {     
    3 @OrderBy(name = "group_name ASC, name DESC")     
    4 private List books = new ArrayList();     
    5 }    

    6.主键生成策略 

     1 public class Users implements Serializable {     
     2 @Id     
     3 @GeneratedValue(strategy=GenerationType.IDENTITY)//主键自增,注意,这种方式依赖于具体的数据库,如果数据库不支持自增主键,那么这个类型是没法用的     
     4 @Column(name = "user_id", nullable = false)     
     5 private int userId;     
     6    
     7    
     8 public class Users implements Serializable {     
     9 @Id     
    10 @GeneratedValue(strategy=GenerationType.TABLE)//通过一个表来实现主键id的自增,这种方式不依赖于具体的数据库,可以解决数据迁移的问题     
    11 @Column(name = "user_code", nullable = false)     
    12 private String userCode;     
    13    
    14    
    15 public class Users implements Serializable {     
    16 @Id     
    17 @GeneratedValue(strategy=GenerationType.SEQUENCE)//通过Sequence来实现表主键自增,这种方式依赖于数据库是否有SEQUENCE,如果没有就不能用     
    18 @SequenceGenerator(name="seq_user")     
    19 @Column(name = "user_id", nullable = false)     
    20 private int userId;    

    7.一对多映射关系 

    有T_One和T_Many两个表,他们是一对多的关系,注解范例如下 
    主Pojo 

     1 @Entity     
     2 @Table(name = "T_ONE")     
     3 public class One implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "ONE_ID", nullable = false)     
     7 private String oneId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10 @OneToMany(cascade = CascadeType.ALL, mappedBy = "oneId")//指向多的那方的pojo的关联外键字段     
    11 private Collection<Many> manyCollection;     

    子Pojo 

     1 @Entity     
     2 @Table(name = "T_MANY")     
     3 public class Many implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "MANY_ID", nullable = false)     
     7 private String manyId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10    
    11 @JoinColumn(name = "ONE_ID", referencedColumnName = "ONE_ID")//设置对应数据表的列名和引用的数据表的列名     
    12 @ManyToOne//设置在“一方”pojo的外键字段上     
    13 private One oneId;     

    8.多对多映射关系 

    貌似多对多关系不需要设置级联,以前用hibernate的时候着实为多对多的级联头疼了一阵子,JPA的多对多还需要实际的尝试一下才能有所体会。 
    估计JPA的多对多也是可以转换成两个一对多的。 
    第一个Pojo 

     1 @Entity     
     2 @Table(name = "T_MANYA")     
     3 public class ManyA implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "MANYA_ID", nullable = false)     
     7 private String manyaId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10 @ManyToMany     
    11 @JoinTable(name = "TMANY1_TMANY2", joinColumns = {@JoinColumn(name = "MANYA_ID", referencedColumnName = "MANYA_ID")}, inverseJoinColumns = {@JoinColumn(name = "MANYB_ID", referencedColumnName = "MANYB_ID")})     
    12 private Collection<ManyB> manybIdCollection;     

    第二个Pojo 

     1 @Entity     
     2 @Table(name = "T_MANYB")     
     3 public class ManyB implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "MANYB_ID", nullable = false)     
     7 private String manybId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10 @ManyToMany(mappedBy = "manybIdCollection")     
    11 private Collection<ManyA> manyaIdCollection;     

    9.一对一映射关系 

    主Pojo

     1 @Entity     
     2 @Table(name = "T_ONEA")     
     3 public class OneA implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "ONEA_ID", nullable = false)     
     7 private String oneaId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10 @OneToOne(cascade = CascadeType.ALL, mappedBy = "oneA")//主Pojo这方的设置比较简单,只要设置好级联和映射到从Pojo的外键就可以了。     
    11 private OneB oneB;   

    从Pojo 

     1 @Entity     
     2 @Table(name = "T_ONEB")     
     3 public class OneB implements Serializable {     
     4 private static final long serialVersionUID = 1L;     
     5 @Id     
     6 @Column(name = "ONEA_ID", nullable = false)     
     7 private String oneaId;     
     8 @Column(name = "DESCRIPTION")     
     9 private String description;     
    10 @JoinColumn(name = "ONEA_ID", referencedColumnName = "ONEA_ID", insertable = false, updatable = false)//设置从方指向主方的关联外键,这个ONEA_ID其实是表T_ONEA的主键     
    11 @OneToOne     
    12 private OneA oneA;     

    10 .大字段 

    1 @Lob //对应Blob字段类型     
    2 @Column(name = "PHOTO")     
    3 private Serializable photo;     
    4 @Lob //对应Clob字段类型     
    5 @Column(name = "DESCRIPTION")     
    6 private String description;    

    11.瞬时字段 

    不需要与数据库映射的字段,在保存的时候不需要保存倒数据库 

     1 @Transient     
     2 private int tempValue;     
     3    
     4 public int getTempValue(){     
     5 get tempValue;     
     6 }     
     7    
     8 public void setTempValue(int value){     
     9 this.tempValue = value;     
    10 } 

    12.总结示例

     1 @Entity                           --声明为一个实体bean    
     2 @Table (name= "promotion_info" )    --为实体bean映射指定表(表名="promotion_info)    
     3 @Id                               --声明了该实体bean的标识属性    
     4 @GeneratedValue                   --可以定义标识字段的生成策略.    
     5 @Transient                        --将忽略这些字段和属性,不用持久化到数据库    
     6 @Column (name= "promotion_remark" )--声明列(字段名= "promotion_total" ) 属性还包括(length= 200 等)    
     7 @Temporal (TemporalType.TIMESTAMP)--声明时间格式    
     8 @Enumerated                       --声明枚举    
     9 @Version                          --声明添加对乐观锁定的支持    
    10 @OneToOne                         --可以建立实体bean之间的一对一的关联    
    11 @OneToMany                        --可以建立实体bean之间的一对多的关联    
    12 @ManyToOne                        --可以建立实体bean之间的多对一的关联    
    13 @ManyToMany                       --可以建立实体bean之间的多对多的关联    
    14 @Formula                          --一个SQL表达式,这种属性是只读的,不在数据库生成属性(可以使用sum、average、max等)   
    15 @Entity    
    16 @Table (name= "promotion_info" )    
    17 public class Promotion implements Serializable {    
    18    
    19      //AUTO--可以是identity类型的字段,或者sequence类型或者table类型,取决于不同的底层数据库    
    20      @Id    
    21      @GeneratedValue (strategy = GenerationType.AUTO)    
    22      private Long id;    
    23    
    24      @Column (name= "group_start_amount" )    
    25      private Integer groupStartAmount= 0 ;    
    26         
    27      @Column (name= "promotion_remark" ,length= 200 )    
    28      //@Lob 如果是文章内容可以使用 只需要把length=200去掉就可以了    
    29      private String remark;    
    30      //DATE       - java.sql.Date    
    31      //TIME       - java.sql.Time    
    32      //TIMESTAMP - java.sql.Timestamp    
    33      @Temporal (TemporalType.TIMESTAMP)    
    34      @Column (name= "start_time" )    
    35      private Date startTime;    
    36    
    37      //显示0 隐藏1    
    38      public static enum DisplayType {    
    39          显示,隐藏    
    40      }    
    41      @Enumerated (value = EnumType.ORDINAL) //ORDINAL序数    
    42      private DisplayType displayType = DisplayType.显示;    
    43    
    44      @Version    
    45      private Integer version;    
    46    
    47      //CascadeType.PERSIST    -- 触发级联创建(create)    
    48      //CascadeType.MERGE      -- 触发级联合并(update)    
    49      //FetchType.LAZY         -- 延迟加载    
    50      @ManyToOne (cascade = {CascadeType.PERSIST,CascadeType.MERGE},fetch = FetchType.LAZY)    
    51      private PromotionGroup promotionGroup;    
    52    
    53      //单向ManyToMany    
    54      //@JoinTable(关联的表名)    
    55      //joinColumns -- promotion关联的列的外键    
    56      //inverseJoinColumns -- largess 关联列的外键    
    57      @ManyToMany (cascade = {CascadeType.PERSIST,CascadeType.MERGE})    
    58      @JoinTable (name= "promotion_largess" ,joinColumns={ @JoinColumn (name= "promotion_id" )},inverseJoinColumns={ @JoinColumn (name= "largess_id" )})    
    59      private Set<Largess> largess;    
    60    
    61      //get set 省略....    
    62    
    63 }    
    64 @Entity    
    65 @Table (name= "promotion_group" )    
    66 public class PromotionGroup implements Serializable {    
    67      @Id    
    68      @GeneratedValue (strategy = GenerationType.AUTO)    
    69      private Long id;    
    70         
    71      //mappedBy的值"promotionGroup"指向owner(Promotion)端的关联属性,并且是双向关系    
    72      @OneToMany (mappedBy= "promotionGroup" ,cascade=CascadeType.ALL)    
    73      private List<Promotion> promotion;    
    74    
    75      //get set 省略....    
    76 }    
    77 @Entity    
    78 @Table (name= "largess" )    
    79 public class Largess implements Serializable {    
    80      @Id    
    81      @GeneratedValue (strategy = GenerationType.AUTO)    
    82      private Long id;    
    83    
    84      //1.sql语句中的字段和表名都应该和数据库相应,而不是类中的字段,    
    85      //若带有参数如la.id= id,这个=id才是类中属性    
    86      //2.操作字段一定要用别名    
    87      @Formula (select max(la.id) from largess as la)    
    88      private int maxId;    
    89    
    90      @Formula (select COUNT(la.id) from largess la)    
    91      private int count;    
    92    
    93      @Transient    
    94      private String img    
    95    
    96      //get set 省略....    
    97 }  
  • 相关阅读:
    BOI 2002 双调路径
    BOI'98 DAY 2 TASK 1 CONFERENCE CALL Dijkstra/Dijkstra+priority_queue/SPFA
    USACO 2013 November Contest, Silver Problem 2. Crowded Cows 单调队列
    BOI 2003 Problem. Spaceship
    USACO 2006 November Contest Problem. Road Blocks SPFA
    CEOI 2004 Trial session Problem. Journey DFS
    USACO 2015 January Contest, Silver Problem 2. Cow Routing Dijkstra
    LG P1233 木棍加工 动态规划,Dilworth
    LG P1020 导弹拦截 Dilworth
    USACO 2007 February Contest, Silver Problem 3. Silver Cow Party SPFA
  • 原文地址:https://www.cnblogs.com/jcjssl/p/9391277.html
Copyright © 2011-2022 走看看