Hibernate

作者: 我不傻_cyy | 来源:发表于2019-12-20 08:28 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:Hibernate

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