JPA的关系映射和JPQL查询

时间:2022-01-28 20:11:41
1.关系映射  
1)多对一  
ManyToOne(@ManyToOne)
Class Order{
@ManyToOne
Customer customer ;
2)一对多  
@OneToMany(targetEntity=Order.class,mappedby=“customer”)
OneToMany(@OneToMany)
Class Customer{
@OneToMany(mappedBy=“”)
Set<Order> orders = ..
}

设置多对一的级联:@ManyToOne(cascade=CascadeType.PERSIST)
3)多对一自连接映射  
@ManyToOne
@JoinColumn(name=“parent_id”,//外键名称
        referencedColumnName=“id”)//当前表主键
Category parentCategory;
4)一对一  
@OneToOne
  class User{
    @OneToOne
    protected Addr addr;

  class Addr{
    @OneToOne(mappedBy=“addr", optional="false");
    protected User user;
  }
5)One-to-one关联  
外键关联:
使用@JoinColumn[单向]
  class User{
    @OneToOne
    @JoinColumn(name=“addr_id", referencedColumnName=“addrid",updatable=false)
    protected Addr addr;
 name指定在用户表中的外键名称.如果没有指定,则生成的外键字段形式如下:
  <relationship字段/属性名>_<对端表的主键名>
  若双向关联的话:
  @Entity
  public class Addr {
    @OneToOne(mappedBy=“addr”)//控制权问题
    protected User user;
主键关联:
One-to-one关联,地址表是自然主键
使用 @PrimaryKeyJoinColumn
  class User{
    @OneToOne
    @PrimaryKeyJoinColumn(name="userid", referencedColumnName=“addrid")
    protected Addr addr;
PrimaryKeyJoinColumn的name属性指定当前表的主键名, referenced-ColumnName属性指定关联表中的外键名称.referencedColumnName默认值属性名_主键名
   public class Addr {
     @Id//自然主键
     @Column(name=“userid")private Integer id ;
     //@oneToOne(mapped="addr") protected User user;
主键关联时,一定要先插入User,然后手动为Addr指定id才可保存.
6)多对多  
  @ManyToMany
  protected Set<Student> students;

  @ManyToMany(mappedBy=“students")
  protected Set<Teacher> teachers;
7)联合主键  
@JoinTable(name="jpa_teas_stus_links",
joinColumns=
  {@JoinColumn(name=“sno1",referencedColumnName=“no1"),
   @JoinColumn(name=“sno2",referencedColumnName=“no2"),
   @JoinColumn(name=“sno3",referencedColumnName=“no3")}
inverseJoinColumns=
  {@JoinColumn(name=“tno1", referencedColumnName=“no1")),
   @JoinColumn(name=“tno2", referencedColumnName=“no2")),
   @JoinColumn(name=“tno3", referencedColumnName=“no3"))}
  protected Set<Stud> studs;

  @ManyToMany(mappedBy="items")
  protected Set<Teacher> teachers;
8)级联删除  
@ManyToMany(mappedName=“teachers”,cascade=CasCadeType.REMOVE)
Set<Student> ..

Em.remove(teacher.class,new CompID(a,b,c));..

2.JPA继承关系  
单表策略:所有的信息存放到一个表中(区分符子段)
  @Entity
  @Table(name=“ess")
  @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
  @DiscriminatorColumn(name=“etype",
            discriminatorType=DiscriminatorType.STRING, length=2)
  public abstract class Employee{..}

  @Entity
  @DiscriminatorValue(value=“he")
  public class HE extends Employee

  @Entity
  @DiscriminatorValue(value=“se")
  public class SE extends Employee

3.实体状态:  
四种状态
  New (transient): 创建出来没关联,没有id,没有记录
  Managed (persistent): 和当前context关联的实体
  Detached: 有id,但不和上下文关联(evict).
  Removed: 有id,不和上下文关联,计划从库中删除.
 
4.持久化相关操作  
  em.persist(fritz);
  em.find( Cat.class, new Long(catId) );
  em.getReference(Parent.class, parentId);
  em.flush();
  em.refresh(cat);
  entityManager.find(Seller.class, sellerId);
联合主键检索:  
  SellerPK sellerKey = new SellerPK();
  sellerKey.setFirstName(firstName);
  sellerKey.setLastName(lastName);
  Seller seller = entityManager.find(Seller.class, sellerKey);
更新实体  
  O o = em.find(..)
  o.setXXX(..);
添加实体:  
  em.persist(..);
合并实体:  
  em.merge(..);//更新游离对象
删除实体  
  entityManager.remove(entityManager.merge(order));
remove只操作托管的实体,如果传递一个游离实体的话,将抛出非法参数异常.
  @OneToMany(cascade=CascadeType.REMOVE)//级联删除
  //Flush控制清理
  em.setFlushMode(FlushModeType.COMMIT);
  em.flush();
  //Refresh
  em.refresh(entity);

5.JPQL查询  
1)简单查询  :
  Query query = em.createQuery("SELECT c FROM Customer c");
  return query.getResultList();
2)命名查询  
  @Entity
  @NamedQuery(name = "findCustomerByName",
              query = "SELECT c FROM Customer c
                                WHERE c.name
                                LIKE :name ")
  class Category{..}
  //定义多个命名查询条件
  @NamedQueries({@NamedQuery(..), @NamedQuery(..)});
  em.createNamedQuery("findAllCustomers")
3)分页  
  query = em.createNamedQuery("findCustomerByName");
  query.setParameter("name", "t,om");
  query.setMaxResults(10);
  query.setFirstResult(3);
  List customers = query.getResultList();
4)设置参数:  
  SELECT o FROM Order i WHERE i.orderNo = ?1
  query.setParameter(1, 100.00);

  SELECT o FROM Order i WHERE o.price = :price
  query.setParameter("price", 100.00);
5)单个实体检索  
  query.getSingleResult();
6)使用实体名  
  @Entity(name = "CustomerEntity")
  public class Category
  FROM CustomerEntity [as] c
7)查询集合  :
  WHERE c.orders IS EMPTY
  WHERE CONCAT(c.fname, c.lname) = 't,om'
  SELECT c.id, c.name FROM Customer c
8)多态查询  
  SELECT c FROM Customer c WHERE c.name LIKE :name
9)分组  
  SELECT o.customer, COUNT(o.id) FROM Order o GROUP BY o.customer
10)排序  
  order by
11)子查询  
  SELECT o FROM Order I WHERE o.customer IN
  (SELECT c FROM Customer c WHERE c.name LIKE ?1)
12)连接  
  SELECT o,c FROM Order o, Customer c WHERE o.customer.id = c.id
  SELECT o FROM Order o [INNER] JOIN o.customer //内连接
  SELECT c FROM Customer c LEFT OUTER JOIN c.orders//外连接
  SELECT c FROM Customer c FETCH JOIN c.orders//迫切连接
13)批量更新/删除  
  UPDATE Customer c SET c.age = ?1 WHERE c.id >=?2
  query.setParameter(1, 12);
  query.setParameter(2, 5);
  int results = query.executeUpdate();