1、hibernate学习笔记建立 Annotation 版本的 HelloWorld1 创建teacher 表,create table teacher (id int primary key, name varhcar(20), title varchar(lO);2 创建Teacher 类3 在hibernate lib 中加入annotation的jar包a) hibernate annotaion jarb) ejb3 persistence jarc) hibernate common-annotations.jard) 注意文裆中没有提到hibernate-common-annota
2、tions.jar 文件4 参考Annotaion文档建立对应的注解5 在hibernate.cfg.xml中建立映射mapping class:./6 参考文裆进行测试(注意文裆中缺少configure()的小bug) 7 FAQ: 不给提示a) 配置eclipse属性信息content assist-activation-加上What is and Why 0/R Mapping1 JDBC操作数据库很繁琐2 Sql语句编写并不是面向对象的3 可以在对象和关系表之间建立关联来简化编程4 0/R Mapping 简化编程5 0/R Mapping跨越数据库平台6 Hibernate_0200
3、_OR_Mapping_SimulationHibernate基础配置对应项目:Hibernate_0300_BasicConfiguration1 介绍MSQL的图形化客户端2 hibernate.cfg.xml: hbni2ddl.auto:create、update。a) 先建表还是先建实体类先建表3 搭建日志环境并配置显示DDL语句a) slf4j与log4j的关系:slf4j像是一个大管家,可以管理许多的日志框架,log4j是其中之一b) 加入slf4j-log4j.jar,加入 log4j 的 jar 包,去掉 slf4-nop.jarc) 从hibernate/project/e
4、tc 目录 copy log4j.propertiesd) 査询hibernate文裆,日志部分,调整日志的输出策略4 搭建jUnit环境a) 需要注意jUnit的Bug5 hibernate.cfg.xml:show_sql 是否输出SQL语句6 hibernate.cfg.xml:format_sql 格式化SQL语句,美化SQL语句 true7 表名和类名不同,对表名进行配置a) Annotation: Tableb) xml:自己査询8 字段名和属性相同a) 不用写column 与默认的Basic效果一样b) Xml中不用写 column9 字段名和属性名不同a) Annotation
5、: Columnb) xml:自己査询10 不需要psersistence的字段(不用列)a) Annotation:Transient 定义不写入数据库,属性透明b) xml不写11 映射日期与时间类型,指定时间精度a) Annotation:Temporal(参数) 参数有3种 只显示时间,只显示日期,时间日期都显示 /Temporal(TemporalType.DATE) 只显示日期 /Temporal(TemporalType.TIME) 只显示时间 /Temporal(TemporalType.TIMESTAMP) 显示日期与时间b) xml:指定 type 12 映射枚举类型( 比
6、较少用)a) Enumerated Enumerated(EnumType.ORDINAL) 枚举类型按位置数,如:0,1,2 .存储 Enumerated(EnumType.STRING) 枚举类型按设定值存储b) xml:麻烦13 字段映射的位置(field或者get方法)a) best practice:保持 field(变量定义) 和 get set 方法的一致14 Lob15 课外:CLOBBLOB类型的数据存取16 课外:Hibernate自定义数据类型17 hibernate 类型ID生成策略 对应项目:hibernate_0400_ID1 注意:a) 我们观察hibernate
7、生成表的结构并不是为了将来就用它生成,(可能还有自己的扩展,比如index等)而是为了明白我们应该建立什么样的表和实体类映射2 xml生成ida) generator b) 常用四个:native identity sequence uuid3 注解方式:GeneratedValuea) 自定义IDb) AUTO(直接写 GeneratedValue 相当如native) (GeneratedValue(strategy=GenerationType.AUTO)i. 默认:对 MySQL,使用auto_incrementii. 对 Oracle使用hibernate_sequence(名称固定
8、)c) IDENTITY(GeneratedValue(strategy=GenerationType.IDENTITY)d) SEQUENCE(GeneratedValue(strategy=GenerationType.SEQUENCE)i. SequenceGenerator(可自定义在数据库生成指定的sequence名) Id/在GeneratedValue中增加 generator=teacherSEQGeneratedValue(strategy=GenerationType.SEQUENCE,generator=teacherSEQ)/teacherSEQ为SequenceGen
9、erator的标识名/teacherSEQ_DB为指定到数据库生成的Sequence名SequenceGenerator(name=teacherSEQ, sequenceName=teacherSEQ_DB) public int getId() return id;e) TABLE (可以忘记)i. TableGeneratorTableGenerator(name=teacherID, /被调用的TABLE名字 table=teacherID_DB, /数据库建立的表名 pkColumnName=key_value, pkColumnValue=pk_value, valueColumn
10、Name=teacher, /pkColumnValue对应类名 allocationSize=1 /pkColumnValue对应类名)GeneratedValue(strategy=GenerationType.TABLE,generator= teacherID ) 注:如果使用注解方式的uuid 如下: IdGeneratedValue(generator=teacherUUID)GenericGenerator(name=teacherUUID, strategy=uuid)4 FAQ;a) 用Junit测试时Hibernate Session Factory初始化异常不提示.疑似一
11、个bugb) 用main来做测试5 联合主键a) Xml方式: composite-idi. 将联合主键的属性提取出来,重新编写一个pojo类(原pojo类中的id,name要删除 并新加入属性“StudentPK”) public class StudentPK implements Serializable private String id; private String name; ii. 新建pojo类必须实现 java.io.Serializable 序列化接口iii. 新pojo类要重写equals和hashCode方法 Overridepublic boolean equals
12、(Object o) if(o instanceof StudentPk) StudentPk pk = (StudentPk)o; if(this.id = pk.getId() & this.name.equals(pk.getName() return true; return false;Overridepublic int hashCode() return this.name.hashCode();iv. 联合主键生成策略XML配置方法 b) Annotationi. 前三步与Xml方式前三步一样 都要建立新pojo类 都要实现Serializable接口 重写equals和has
13、hCode方法.ii. 方法1在新类前写Embeddable,在原pojo类的新属性“TercherPK”的get方法前写ld,如下 Embeddablepublic class TeacherPK implements Serializable private String id; private String name; Entitypublic class Teacher private TeacherPK teacherPK ;Idpublic TeacherPK getTeacherPK() return teacherPK; iii. 方法2:EmbeddedlD(*) 新pojo
14、类无需加注解,只需在原pojo类新属性“TercherPK”的get方法前写EmbeddedlD即可iv. 方法3:Id IdClass(*) 新pojo类无需加注解,原pojo类的id,name属性保留不变,也无需新增“TercherPK”属性。 只在id,name的get方法前都加Id,并在原pojo类前加“IdClass(TeacherPK).class)”,如下EntityIdClass(TeacherPK.class)public class Teacher private String id;private String name;Idpublic String getId() r
15、eturn id;Idpublic String getName() return name;. .核心幵发接口介绍 hibernate_0500_CoreAPI1 Hibernate API文档需要单独下载2 Configurationa) AnnotationConfigurationb) 进行配置信息的管理c) 用来产生SessionFactoryd) 可以在configure方法中指定hibernate配置文件e) 只气关注一个方法即:buildSessionFactory3 SessoinFactorya) 用来产生和管理Sessionb) 通常情况下每个应用只需要一个Session
16、Factoryc) 除非要访间多个数据库的情况d) 关注两个方法即:openSession getCurrentsessioni. open session每次都是新的,需要closeii. getCurrentsession从上下文找,如果有,用旧的,如果没有,建新的1. 用途,界定事务边界2. 事务提交自动close3. 上下文配置可参见xml文件中 thread4. current_session_context_class (jta、thread常用 managed、custom.Class少用) a) thread 使用connection 但数据库连接管理事务 b)jta (全称j
17、ava transaction api)-java分布式事务管理(多数据库访问) jta由中间件提供(jboss WebLogic等,tomcat不支持)4 Sessiona) 管理一个数据库的任务单元(简单说就是增 删 改 查)b) 方法(CRUD)i. Save() session.save(对象);ii. Delete session.delete(对象);iii. Load Student s1=(Student)session.load(Student.class, 1);iv. Get Student s1=(Student)session.get(Student.class, 1
18、);v. get与load的区别(面试重点,原理)1. 不存在对应记录时表现不一样2. load返回的是代理对象,等到真正用到对象的内容时才发出sql语句3. get直接从数据库加载,不会延迟vi. updates session.update(对象);1. 用来更新detached对象,更新完成后转为persistent状态2. 更新transient对象会报错3. 更新自己设定id的transient对象可以(数据库有对应记录)4. persistent状态的对象只要设定(如:t.setName)不同字段就会发生更新5. 更新部分更改的字段a) xml 设定 property 标签的 up
19、date 属性,annotation 设定Column 的 updatable 属性,不过这种方式很少用,因为不灵活(忘记)b) 使用xml中的dynamic-update,JPA1.0 Annotation 没有对应的属性,hibernate 扩 展? i. 同一个session可以,跨session不行,不过可以用merge()(不重要)c) 使用 HQL(EjBQL)(建议)vii. saveOrUpdate() session.saveOrUpdate(对象);viii. clear方法 session.clear();1.无论是load还是get,都会首先査找缓存(一级缓存),如果没
20、有,才会去数据库査找,调用clear()方法可以强制清除session缓存ix. flush()方法 session.flush();1. 当session的事务提交后,会强制将内存(session缓存)与数据库同步.默认情况下是session的事务提交(commit)时才同步!2. session的FlushMode设置,可以设定在什么时候同步缓存与数据库(很少用) 例如: session.setFlushMode(FlushMode.AUTO)x. find方法已经过时!5 SchemaExport (自动建表) new SchemaExport(new AnnotationConfigu
21、ration().configure().create(false, true);6 Query 接口a) 参考Hibernate査询(HQLEJBQL)的内容7 Note:a) Hibernate中涉及很多非常非常细节的区别,但在实际应用中用得极少,请大家先享受写项目的乐 趣,再来探讨这些细节问题i. 比如save和persist的区别ii. merge、evict 等方法iii. 比如 refresh、lock 等b) 建议的学习方法,动手实验c) 细节问题参考补充视频1 上一个 project2 三种状态的区分关键在于a) 有没有IDb) ID在数据库中有没有c) 在内存中有没有(ses
22、sion缓存)3 三种状态:a) transient:内存中一个对象,没ID,缓存中也没有b) persistent:内存中有,缓存中有,数据库有(ID) c) detached:内存有,缓存没有,数据库有,ID4 对这三种状态需要关注的问题是在该状态下如果进行数据库的操作会发生什么结果,比 如改变属性的 值会不会发出update语句?a) 强烈建议动手实验b) 进行正常人的思考c) 绝对不要去背这些东西!背过也并不代表你有多牛!关系映射(重要) 对象之间的关系1 这里的关系映射指的是对象之间的关系,并不是指数据库的关系,本章解决的问题是当对象之间处于下列关系之一时,数据库表该如何映射,编程上
23、该如何对待(红色为重点中的重点)2 简化问题:a) 怎么写 Annotationb) 增删改査CRUD怎么写3 对一a) 单向(主键、外键)b) 双向(主键、外键)c) 中间表4 对多a) 一张主表,多张子表5 组件映射a) Embeddableb) Embedded一对一关联1 一对一单向外键关联a) 项目名称:hibernate_0600_one2one_uni_fkb) Annotation: 在被约束表字段的get方法上加0ne20ne JoinColumn OneToOne JoinColumn(name=wifeid) /指定生成的数据库字段名 public Wife getWif
24、e() return wife; c) xml: 在被约束表的xml配置文件中加many-to-one unique unique=true是保证生成的字段唯一,这样many-to-one 也达到了一对一的效果2 一对一双向外键关联a) 项目名称:hibernate_0700_one2one_bi_fkb) Annotation: 0ne20ne(mappedBy=”另一个类里定义的属性名”) 规律:凡是双向关联,必设mappedBy 在Wife类中 写Husband对象属性 并添加注解OneToOne(mappedBy=wife) mappedBy作用是指定这个一对一关联是被Husband类
25、的 wife属性(准确说是getWife方法)做的映射OneToOne(mappedBy=wife) public Husband getHusband() return husband; 在 类中写Wife对象属性 OneToOne JoinColumn(name=wifeid) /指定生成的数据库字段名 public Wife getWife() return wife; 此注释将由Husband表中生成wifeid字段作为fk外键,wife表中不生成额外的Husbandid字段c) xml: many-to-one unique one-to-one property-ref 在Stud
26、ent类中写StuIdCard属性, StuIdCard类中写Student属性 StuIdCard.hbm.xml文件中加 Student.hbm.xml文件中加其中, property-ref 相当于mappedBy此方式生成的StuIdCard表中包含studentid字段作为fk外键, Student表中不生成额外的字段特别说明: 一对一单向外键关联与一对一双向外键关联在数据库的表的格式是一样的,区别在于java程序中. 双向外键关联可通过Hibernate在两个类间互相调用彼此,而单向外键关联只能单方向调用.3 一对一单向主键关联(不重要,忘记)a) 项目名称:hibernate_0800_one2one_uni_pkb) primaryKeyJoinColumnc) xml: one-to-one id 使用 foreign class4 一对一双向主键关联(不重要,忘记)a) 项目名称:hibernate_0900_one2one_bi_pkb) primaryKeyJoinColumn(不常用,了解)c) xml: one-to-one id 使用foreign class和one-to-one proper
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1