加入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: <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings (hibernate自动帮你链接了数据库,填入相关信息) --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">abc123</property> <!-- JDBC connection pool (use the built-in) (hibernate的连接池) --> <!-- <property name="connection.pool_size">1</property> --> <!-- SQL dialect (hibernate方言,hibernate统一了sql语言,将统一语言翻译成下面填写的相应的数据库语言) --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property> <!-- Disable the second-level cache (将二级缓存disable掉) --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout (将生成的sql语句打印出来) --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup (是否让hibernate自动生成ddl(建表语句)) --> <!-- <property name="hbm2ddl.auto">update</property> --> <mapping resource="com/bjsxt/hibernate/model/Student.hbm.xml"/> </session-factory> </hibernate-configuration> 还要指明object与表字段的对应关系。建立映射文件,Studnet.hbm.xml: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.bjsxt.hibernate.model"> <class name="Student"> //找到对应的类 <id name="id" column="id" /> //id表示为主键 <property name="name" /> //property表示一般字段 <property name="age" /> </class> </hibernate-mapping> 写测试类: 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设定: <property name="cache.use_second_level_cache">true</property> //打开二级缓存 <property name="cache.provider_class">org.hibernate.cache.EnCacheProvider</property> //指明使用哪种二级缓存 添加注解: @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的问题(依赖于数据库的锁)