Hibernate零散笔记

加入mysql的驱动mysql-connector

在数据库中建立相应的内容:
create database hibernate;

use hibernate;

create table student(id int primary key, name varchar(20),age int);

建立student类:


建立hibernate配置文件,hibernate.cfg.xml:






    

        
        com.mysql.jdbc.Driver
        jdbc:mysql://localhost/hibernate
        root
        abc123

        
        

        
        org.hibernate.dialect.MySQLDialect

        
        thread

        
        org.hibernate.cache.NoCacheProvider

        
        true

        
        

        
        
    



还要指明object与表字段的对应关系。建立映射文件,Studnet.hbm.xml:





        //找到对应的类
            //id表示为主键
            //property表示一般字段
        
    


写测试类:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.bjsxt.hibernate.model.Student;



public class StudentTest {
    public static void main(String args[]){
        Student s = new Student();
        s.setId(1);
        s.setName("s1");
        s.setAge(1);
        
        Configuration cfg = new Configuration();
        SessionFactory sf = cfg.configure().buildSessionFactory();    //SessionFactory产生connecyion的工厂
        Session session = sf.openSession();
        session.beginTransaction();
        session.save(s);    //将对象s插入数据库
        session.getTransaction().commit();
        session.close();
        sf.close();
    }
}

annotation(利用annotation注解就可以不用*.hbm.xml文件):
建立新表:
create table teacher (id int primary key,name varchar(10),title varchar(20));

建立对象Teacher并加入注解annotation:

package com.bjsxt.hibernate.model;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity    //表示实体类,对应于数据库表中的一个表
public class Teacher {    //利用annotation注解就可以不用*.hbm.xml文件
    private int id;
    private String name;
    private String title;
    
    @Id    //表示主键
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

JDBC操作数据库很繁琐
sql语句是面向关系而不是面向对象
可以再对象和关系表之间建立关系来简化变成
o/r mapping跨越数据库平台

表名与类名不同的时候,对表名进行配置
    Annotation:@Table
    xml:...

字段名与属性相同的时候:默认为@Basic;xml中不写column

字段名与属性名不同的时候:
    Annotation:@Column
    xml:...

不需要psersitence(持久化,存入数据库)的字段:
    Annotation:@Transient
    xml:直接不写

映射日期与时间类型,指定时间精度:
    Annotation:@Temporal
    xml:制定property标签的type属性

枚举类型的映射:
    Annotation:@Enumerated
    xml:...

注解的位置:
    可以放在field(成员变量)上面,
    也可以放在getxxx方法上面。

Junit4有BUG:第19个视频

ID生成策略:对应项目hibernate_0400_ID
注意:
    我们观察hibernate生成表的结构并不是为了将来就用他生成(也可能还有自己的扩展,比如index),而是为了明白我们应该尽力什么样的表和实体类映射。

xml生成id:
    使用generator
    常用的有四个:native identity sequence uuid
annotation生成id:
    @GeneratedValue
    有四种取值方式:auto identity sequence(@SequenseGenrator) table(@TableGenerator)

联合主键:
    xml:composite-id(要实现serializable和重写equals和hashcode)
    annotation:
        将类注解为@IdClass,并将该类实体中的所有属于主键的属性都注解为@Id
        将组件类注解为@Embeddable.并将组件的属性注解为@Id
        将组建的属性注解为@Embeddable
        
    
Hibernate的核心开发接口:
    sessionFactory有两个方法得到Session:
    1.openSession:每次都打开一个新的Session,用完要关闭
    2.getCurrentSession:拿到当前上下文(可以在配置文件中设置current-context-class,主要有jta和thread)已有的Session或者打开一个新的Session(前一个Session被commit之后),用完不用关闭,commit()之后自动关闭。
    Session是个接口,这两种方法得到的具体类可能不一样,所以不能混用
    两种方法的区别很重要
区别在第26集。
    JPA界定事物边界,例如数据存入和日志记录需要在同一个事物之内完成。
    还有一种事物JTA,分布式数据库。


对象的三种状态:
    怎么区分:
    1.对象有没有ID
    2.ID在数据库中有没有
    3.在内存(session缓存)中有没有ID
1.transient:内存中一个对象,没ID,缓存中也没有ID
2.persistent:内存中有ID,缓存中有ID,数据库有ID
3.detached:内存有ID,缓存没有ID,数据库有ID

delete方法:
    只要有ID就可以调用delete方法

get和load的区别:
    get会马上执行sql语句得到对象
    load会生成并返回一个代理对象,直到你取该对象的属性,这个代理才会执行sql语句得到对象
不存在对应记录的时候有区别。

update:
    用来跟新detached对象,更新完成后可以转化为persistent状态
    更新transient会报错
    跟新自己设定ID的transient对象可以(前提是数据库有对应记录)
当一个persistent对象的字段被改变的时候,commit会检查修改,且更改全部字段。
下面的方法只让他修改相应的修改了的字段:第32个视频。

clear:
    无论是load还是get,都会先查找缓存,如果没有,才会去数据库查找,调用用clear方法可以强制清除Session缓冲。

flush:
    可以强制进行从内存到数据库的同步,commit时就执行一次flush。


关系映射:
对象之间的关系:

一对一:
    单向:
        每个Husband对应一个Wife,Wife中没有对应的Husbus,则此为单向关联
        在数据库有中用外键关联
        @OneToOne @JoinColumn(name="wifeId")
    双向:
        每个Husband对应一个Wife,Wife中也对应一个Husbus,则此为双向关联
        @OneToOne(mappedBy)
    联合主键:
        @JoinColums
一对多(多对一):
    设局库表设计:在多的一方加外键。

多对多:    
    单向关联:
        老师和学生的关系,老师需要知道自己教了哪些学生。
    双向关联:
        老师知道自己教了哪些学生,学生也知道教自己的有哪些老师。

此外还可以根据单向还是双向可以非为7种。

Ctrl+Alt+下    复制这一行到下一行
Alt+下    移动这一行到下一行
powerdesigner可以用于分析代码,生成表的关系图。

关联关系中的CRUD:
    设定cascade可以设定在持久化时对于对象的操作。
    C--create
    R--retrieve(取出load get)
    U--update
    D--delete
Cascade属性致命做什么操作的时候关联对象是绑在一起的
Merge=save+update
refresh=A里面需要读B改过之后的数据

铁律:双向关系在程序中要设定双向关系,双向关系设定mappedBy(在一的那一方设置)

fetch:
    双向不要两边设置Eager(会有多余的查询语句发出)
对多的乙方设置fetch的时候要谨慎,结合具体情况,一帮使用Lazy不使用eager(特别情况:多方的数量不是很多的时候可以考虑,提高效率的时候可以考虑)。

O/RMapping编程模型:
1.映射模型
    jap annotation
    hibernate annotation extension
    hibernate xml
    jap xml
2.编程接口
    jap
    hibernate
3.数据查询:
    hql
    ejbql(jpql)

要删除或者更新的时候,先load,除了精确知道ID号之外。

如果要消除关联关系,先设定为NULL,在删除记录,如果不删除记录,该记录就会变成垃圾数据。第51集。

如果指定@OneToOne的属性fetch为FetchType.LAZY,会延迟对于关联对象的加载,不论使用的是load还是get。

关系映射总结:什么样的关系,设计什么样的表,进行什么样的映射。

继承映射:
    1.一张表single_table
    2.每个类分别一张表table_pre_class
    3.每个子类一张表joined

树状结构的设计(至关重要):
    在用一个类中使用one2many和many2one。

Hibernate查询(query language)
HQL&EJBQL
1.NativeSQL
2.HQL(Hibernate ql)
3.EJBql(JPql 1.0)--可认为是hql的子集
4.qbc
5.qbe


性能优化:
    注意session.clear()的使用,尤其在不断分页循环的时候,否则会造成内存泄漏。
JAVA有内存泄露吗?
    在语法级别上没有,但是在实际上可能会间接造成,如果他调用用了C,在调用OS,而C需要手动控制内存。

1+N问题(很重要):
    第64集
解决方案:
    1.设置LAZY
    2.BatchSize
    3.join fetch
用得最多的是1 3。

list和Iterate的区别:
    1.list取所有
    2.iterate先去ID,等用到的时候再根据ID来去对象
    3.session中list第二次发出,仍会到数据库查询
    4.iterate第二次发出,则会先找session缓存

hiberbate中有三种缓存:
    1.一级缓存(Session级)

    2.二级缓存(SessionFactory级)
        可以跨Session存在
    以下情况使用二级缓存:
        1.经常被访问
        2.不会经常改动
        3.数量有限
        如:用户权限、组织机构
hibernate.cfg.xml设定:
    true    //打开二级缓存
    org.hibernate.cache.EnCacheProvider    //指明使用哪种二级缓存
添加注解:
    @Cache
load默认使用二级缓存,iterate默认使用二级缓存
list默认往二级缓存加数据,但是查询的时候默认不使用
    3.查询缓存
只有在查询语句完全一样才有效。查询缓存依赖于二级缓存,所以必须同时打开二级缓存。
调用Query的setCachable(true)方法指明使用二级缓存。

缓存算法:(当缓存满了之后怎么办)
    1.LRU:Least Recently Used(最近最少被使用的被清除)
    2.LFU:Least Frequently Used(使用频率最少的被清除)
    3.FIFO:First In First Out(先来的先被清除)
可以在ehcache中设置使用哪一种:
    memoryStoreEvictionPolicy="LRU"

事物并发处理:
事物的特性:ACID
Atomic(原子性) Consistency(独立性) Itegrity(一致性) Durability(持久性)
事物经常出现的问题:
    脏读 不可重复读 幻读 
数据库的事物的隔离机制:
1:read-uncommitted
2:read-committed
4:repeatable read
8:serilizable
只要数据库支持事物,就不可能出现第一类丢失跟新。
read-uncommitted会出现dirty read,phanton-read,non repeatable read问题。
read-committed不会出现dirty read,因为只有另一个事物提交才会读出来结果,但仍然会出现phanton-read,non repeatable read.
repeatable read。
serial解决一切问题。
设定hibernate的事物隔离级别:
    一般设定hibernate.connection.isolation=2    //考虑效率
    用悲观素解决repeatable read的问题(依赖于数据库的锁)

 

转载于:https://www.cnblogs.com/mosquito-woo/p/3880737.html

你可能感兴趣的:(Hibernate零散笔记)