Hibernate

2019-12-20  本文已影响0人  我不傻_cyy

Hibernate中常用的注解
@Entity表示该类是持久化类
@Table表示将该类映射到对应的表
@Id表示主键ID
@GenerateValue表示主键生成策略
@Column表示属性和字段的映射
@Transient表示忽略该属性
@OneToMany表示一对多
@ManyToOne表示多对一
@ManyToMany表示多对多
@OneToOne表示一对一
如果不想使用id作为主键,可以使用例如下面的这种方式

<property name="属性名称" type=“类型” column=“数据库字段名称”>
    <generator class="assigned">
</property>
assigned表示主键由用户决定

@OneToMany一对多单向配置时:

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "Category")
public class Category {

    private Long id;
    private String type;
    private List<Product> products;


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    @Column(name = "type")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JoinColumn(name = "cid")//name使用的是数据库字段名
    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }
}

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;

@Entity
@Table(name = "Product_")
public class Product {

    private Long id;
    private String name;
    private Double price;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "price")
    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

@OneToMany双向配置

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "Category")
public class Category {

    private Long id;
    private String type;
    private List<Product> products;


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    @Column(name = "type")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
//mappedBy表示在多的一方Category的属性名,防止生成中间表
    @OneToMany(cascade = CascadeType.ALL,mappedBy = "category")
    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }
}

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;
import org.hibernate.annotations.ManyToAny;

import javax.persistence.*;

@Entity
@Table(name = "Product_")
public class Product {

    private Long id;
    private String name;
    private Double price;
    private Category category;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "price")
    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @ManyToOne
    @JoinColumn(name = "cid",referencedColumnName = "id") //name表示在本表中的数据库字段名,referencedColumnName表示对应的在连接的表中的数据库字段名
    @Basic(fetch=FetchType.LAZY)
    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }
}

Hibernate中的Session接口是Hibernate向应用程序提供数据库操作的主要接口,它提供了基本的增删改查java对象的方法。
Session中的缓存:
session缓存是hibernate的一级缓存,Session缓存可以减少Hibernate应用访问数据库的频率。
session中的flush():将缓存中的对象属性变化更新数据库中的记录,使缓存中的对象和数据库记录保持一致。
调用flush()的时间点有:
1.手动调用flush()方法
2.事务提交的时候,会首先调用flush()方法,然后再提交事务
3.当程序执行一些查询操作的时候,如果缓存中的对象的属性已经发生变化,会先调用flush()方法,将变化更新到数据库中,以保证查询的对象属性是最新的。
session中的refresh()方法:刷新缓存中的数据
session中的clear()方法:清除缓存

实体对象在hibernate中的三种状态:
1 . 临时状态:对象创建出来,没有session管理,数据库中没有记录。

  1. 持久化状态:实体对象在数据库中有记录,并且有session管理。
  2. 游离状态:实体对象在数据库中有记录,但是对应的session已经关闭。

HIbernate的三种查询:

  1. HQL(HIbernate Query Language):Hibernate专门的查询语言
    是使用类名而不是表名,不需要写select *,
    例如:
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
Query q = session.createQuery(' from Product p where p.name like ? ');//Product使用的是类名
q.setString(0,"%" + name + "%" );
List<Product> products = q.list();
......
  1. Criteria查询完全是面向对象的,完全看不到语句
    例如:
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
Criteria c = s.createCriteria(Product.class);
c.add(Restrictions.like("name","%"+name+"%"));
List<Product> products = c.list();
......
  1. 使用标准的SQL语句进行查询
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
String sql = "select * from product_ p where  p.name like "%"+name+"%"";
Query q = session.createSqlQuery(sql);
List<Product> products = q.list();
......

HIbernate事务:
Hibernate中任何对数据进行改动的操作都应该放在事务中。一个事务中,多个操作要么都成功,要么都失败。
事务是由Session的beginTransaction()开始,由Session的getTransaction().commit()结束。
HIbernate延迟加载:
属性延迟加载:使用load()方法取对象的时候,如果不访问对象的属性,是不会去数据库中查找该对象。只有在访问该对象的属性的时候,才会去数据库中查找该对象。
关系延迟加载:在一对多或多对多关系中可以设置延迟加载,在取多的对象的时候才去查数据库加载。
HIbernate级联:
如果配置了级联,简单的说就是删除一个一方时,其对应的多的一方也会被删除。
有四种类型的级联

  1. all:所有的数据库操作都执行级联操作
  2. none:所有的数据库操作都不执行级联操作
  3. delete:删除操作执行级联操作
  4. save-update:执行级联操作
    默认是none
    Hibernate的一级缓存和二级缓存:
    Hibernate的一级缓存:默认开启一级缓存,一级缓存放在session上
    例如:
public static void main(String[] args){
       SessionFactory sf = new Configuration().configure().buildSessionFactory();

       Session s = sf.openSession();
       s.beginTransaction();
       Category p1 = (Category) s.get(Category.class, 1);
       Category p2 = (Category) s.get(Category.class, 1);
       s.getTransaction().commit();
       s.close();
       Session s2 = sf.openSession();
       s2.beginTransaction();
       Category p3 = (Category) s2.get(Category.class, 1);

       s2.getTransaction().commit();
       s2.close();
       sf.close();
   }
上面的代码中,获取p1的时候会执行sql查询,获取p2的时候不执行sql直接从缓存中取,获取p3的时候执行sql,因为它们不是同一个session

Hibernate二级缓存:
二级缓存是放在SessionFactory上,二级缓存需要使用第三方插件开启
上面的代码中,只有在获取p1的时候执行sql查询,获取p2、p3的时候都不需要执行sql查询,直接从缓存中取。

Hibernate的分页:
使用Criteria的setFirstResult和setMaxResults实现分页

SessionFactory sf = new Configuration().configure().buildSessionFactory();

       Session s = sf.openSession();
       s.beginTransaction();
       Criteria criteria = s.createCriteria(Category.class);
       criteria.add(Restrictions.like("name","%"+"iphone"+"%"));
       criteria.setFirstResult(3);    //从第4条开始
       criteria.setMaxResults(5);  //一共查询5条数据

Hibernate中的load和get的区别:
get不会延迟加载,会立即执行查询,当查询对象不存在的时候,返回null
load会延迟加载,在访问对象的属性或方法的时候,才去查询对象,当查询对象不存在的时候,会报错。
Hibernate中两种获取session的方式:
openSession():每次都会获取一个新的session,查询操作不需要事务,其他操作需要事务。
getCurrentSession():在同一个线程中,每次获取的都是同一个session,增删改查操作都需要事务。事务提交之后会自动关闭。
Hibernate的乐观锁:
当多个用户同时修改某个数据的时候,就会出现问题,这个时候可以给对象上添加version字段,用于版本控制,version字段必须紧挨着id字段。
当一个用户修改了数据库对象的时候,相应的version也会改变,当另一个已经获取version改变前的对象,进行修改操作的时候会和数据库中该对象当前的version进行比较,如果version不等于数据库中该对象当前的version,操作就会失败。

深入理解session中的flush()方法:
例如:

SessionFactory sf = new Configuration().configure().buildSessionFactory();

        Session s = sf.openSession();
        s.beginTransaction();

        Product o = (Product) s.get(Product.class, 1);     //从数据库中查id为1的product
        System.out.println(o.getName());          //会把查询结果保存到session中
        o.setName("iphone7");                    
        s.flush();                //准备执行update操作
        System.out.println(o.getName());       //获取到的是更新后的名字
        Product o1 = (Product) s.get(Product.class, 1);   //从session中获取
        System.out.println(o1.getName());

输出为:
Hibernate: select product0_.id as id0_0_, product0_.name as name0_0_, product0_.price as price0_0_ from product_ product0_ where product0_.id=?
iphone
Hibernate: update product_ set name=?, price=? where id=?
iphone7
上一篇下一篇

猜你喜欢

热点阅读