1.建立第一个程序 model里面是数据库表所对应的字段,先建立strudent数据库,再建立与数据库与之对应的model,再从官方的文档里面copy hibernate.cfg.xml文件并进行修改,
-->建立student.hbm.xml文件
2.在student.hbm.xml文件中<hibernate-mapping package =是你要映射到的哪个包中 class name=“为那个包中所对应的类名” table="数据库的表名"(它包含这个类和表之间的映射关系) id name=“为model中的那个主键” column=‘与DB中对应的列’>同时要在hibernate.cfg.xml文件中的<mapping-resource>指定要映射的strudent.hbm.xml文件。
3.写具体的实现,前几步是固定的写法,也可以定义一个工具类进行封装
SessionFactory sf=new Configuration.configure.buildSessionFactory();
Session session=sf.openSession();
Transfaction ts=session.beginTransfaction(),
在hibernate中操作要放在事物里面,session.save(这个s是一个student类对象)
ts.commit();提交事务。
4.在3中执行save时候,hibernate是这样做的,发现s是一个student类,那么hibernate就会到hibernate.cfg.xml文件中的mapping-resource中找到对应的student.hbm.xml文件,然后再将student.hbm.xml中的id,通过getId方法向数据库save保存对应的那个字段名,然后hibernate就会拼接sql语句,连接数据库等一系列的jdbc操作,这样在执行save方法时,数据库中就会有数据了。
5.hibernate3.0以后支持注解,以下是用注解来完成和之前一样的功能,将student中的字段保存到DB中去。。
先用@Entity这是一个实体类(放在类名之前)意味着下面的类是一个实体类,它在DB中有对应的表和字段,然后再在getId中注解一个@Id表示这是一个主键,接着在hibernate.cfg.xml文件中用<mapping class指定所对应的model即 com,wt.student>最后在sessionFactory中new一个AnnotationConfiguration,其他和3中一样。
6. 在student.hbm.xml文件中<property name='hbm.iddl.auto'>create</property>当在DB中没有对应的表时会自动创建一个新表,里面包含还有validate,update,create-drop等。
7.在实际开发中是先建表,再建类,hibernate的日志框架用的是slf4j,将hibernate的日志也就是slf4j转换为log4j的话,需要用到slf-log4j.jar。
junit,先引入junit的jar包,然后对想测试的类的方法进行测试时,需要用到@Test,在测试某个方法时,可以使用 @BeforeClass在类初始化前就将sessionFactory给初始化,以便共享,在测试某个方法结束之后,再用@AfterClass将sessionFactory关闭就可以了。
8.当字段名和属性不一样时,在注解的时用@Column(name='你DB中的字段名')也可以在xml文件中用<property column='你对应的DB字段'>,当不想将某个属性被映射到DB时,可以用@Transient作用在对应属性的get方法上,这样在DB就没有对应的字段了,而在xml文件只需要在<property name>中不写就可以了。
9.当需要记录日期或只有时间时,就用@Temporal在对应的Date类型变量的get方法就可以了,当用Annotation映射Enumation(枚举)时,只要在对应的get方法上加上@Enumerated(EnumType...)即可。
10.在xml中可以有native,identity,sequence,当在mysql中用native进行id生成策略时,可以使用的是auto_increatement,用Annotation来进行Id生成策略时,用@GeneratedValue在id上,默认用的是auto,会自动生成id。
11.当在oracle中指定生成主键和sequence时,可以用@sequenceGenevator(name='指定名字A' sqquenceName="在DB中的sequence名")这个主键要在类之前,同时在id上用@GeneratedValue(strategy=Generation_sequence,generator='指定名字A')
12.联合主键要重写equals和hashcode方法,为了保证对象在内存中的唯一性,联合主键是将两个或两个以上的字段作为主键,如id和name,那么需要定义一个类studentPK实现serializable接口,并重写equals和hashcode方法,同时在hbm.xml文件中有<composite-id 和key-property指出被操作时候的联合主键的类和联合主键>(这是用xml方式实现联合主键的)
13.联合主键用Annotation时,先定义一个studentPk 同上,有两种常用的注解方式(1).用@EmbeddedId在model中的studentPK的getPK方法上,表示这是一个联合主键,
(2)用@id分别在model中的getID和getName方法上,同时还要用@IdClass指定studentPK为联合主键(注意@IdClass在model类上面)。
14.sessionFactory是产生与数据库的连接,主要的维护东西是DB连接池,当产生session时会从DB连接池中建立一个连接,一般sessionFactory为单例的,是通过openSession/gerCurrentSession表示如果上下文中(也就是说,如果hibernate.cfg.xml文件中的current_session_context_class)的thread中有session就用那个session,当没有时,就创建一个新的session,而openSession永远是创建一个新的session.
当用getCurrentSession一旦提交即:commit之后,再用getCurrentSession就是一个全新的session,而openSession需要手动的close,getCurrentSession事务提交后会自动的close。
15.写文档中的3种状态,save将Transisent状态转换为presistent状态,三种状态: 1)transisent内存中一个对象,没有ID缓冲中也没有对象。
2)presistent:内存中有,缓存中有,数据库中有ID
3)detached:内存有,缓存没有,数据库有。
三种状态的区分关键在于:
有没有ID ,ID在数据库中的位置,内存中有没有(session缓存)。
16.delete方法只使用于只要是DB有要删除的ID,那么就可以删除掉,get,load方法是从DB取出数据,再转换为对应对象,get.load.的区别:
(1)不存在对应记录时,表现不一样,load返回的是一个代理对象,等到真正用到对象的内容时,才发出sql语句,而,get直接从DB中加载,不会延迟。
(2)当不存在对应的记录时,load在没有真正用到的时,不会报错,用到了对应的记录时才会报错,而get当没有时就会报错。
17.当presistent对象里面的值被改变时,就会发出update语句来更新所有的字段,当里面的值相同时,不会发出upadte语句。
更新update session.update(对象)
(1)用来更新detached对象,更新完成后转换为persisent状态。
(2)更新transisent对象会报错,更新自己设定的ID的transient对象可以(前提是数据库中有对应的记录),persisent状态的对象只要设定不同字段(日:t.setName)就会发生更新。
(3)更新部分更改的字段。
在hbm.xml设定property标签的update属性,annotation设定@Column的update,属性的方式也就是xml文件方式,很少使用,不灵活,当不要某个字段在别的字段更新时,而自动更新,可以使用@Column中的updateable=false即可。
18.无论是load,get都会先去查找缓存(一级缓存)如果没有才会去DB查找,调用clear方法,可以强制将session清除,让其每个都从数据库中进行查找。
(2)flush方法,当session的事务提交后,会强制将内存(session缓存)与数据库同步,默认情况下是session事务提交commit才同步。
19.关系映射。这里说的关系映射指的是对象之间的关系,并不是指数据库的关系,主要解决的问题是当对象之间处于关系时,数据库表该如何映射,有
(1)一对一单向外键关联,在husband model中写wife w的set/get方法同时在getWife方法上用@One2One @JoinColumn(name="wifeid")
当在xml配置时用的是onetoone配置是:<many-to-one name="student";column="studentId" unique="true">
20.一对一双向外键关联。当两个类都有对方的引用时,如:husband类中有 wife w的引用,wife类中有Husband h的引用,若用Annotation方式的话,两个类中都用@OneToOne这样的话husband表中有wife_id,wife表中有husband_id,这样就有点冗余,所以在wife类中的@oneToone@JoinColumn(name="wifiID")表示外键中的主导在husband中,不用关联wife类中的,这样在wife表中就没有wife_id了,而在Husband中用注解@onetoone(mappedBy="wifi")若用xml文件时,在wife.hbm.xml文件中是<one-to-one name="husband" property-ref="wife">在husband.hbm.xml文件中有<many-to-one name=‘wife’ column='husbandId' unique="true">那么这样在双向外键时,就只有husband中有外键了,wife中没有husbandId外键了,减少了冗余。
21.规律:凡是双向关联必有mappedBy,一对一单向外键关联与一对一双向关联在DB表中的格式是一样的,区别在于java中,双向外键关联可通过hibernate在两个类之间相互调用,而单向外键关联只能单向调用。
22.一对一外键关联中都有@onetoone,在husband中有@joinColumn(name='wife')而在一对一单向主键关联时都有@onetoone,在husband中有@primarykey joinColumn,当用xml时,将husband.hbm.xml修改为<one-to-one name="wife">就成为了一对一单向主键关联,而一对一的双向主键关联中都有@onetone和@PrimanyKeyJoinColumn.
23.组件映射,用注解方式,有husband,wife两个类,想共同使用一张表的话,可以用这个映射,在husband类中有getWife方法,且有@Embeded注解,这样两个类就有一张表了,用xml方式的话,进行组件映射的话,在husband.hbm.xml文件中用<componet name='wife'><property name='wifename'><property name='wifeage'></compoment>这表示wife类是一个husband类中的一部分。
24.多对一的单向关联,在多的那方写上一的那方的set,get方法和@manytoone.如:一个组有多个成员,一个成员只属于一个组,那么再user类中就要有group类的get,set方法,同时在get方法上写@manytoone,.如果用xml则在多的那方,也就是在user方,设置<many-to-ont name='group' column='groupid'>
25.一对多的单向关联,在一的那方有多的那方集合的话,即在group类中有user的集合,set<user> users=new HashSet<User>().且有对应的users集合的set,get方法并且在get方法用@onetomany hibernate默认的将一对多单向处理为多对多的特殊情况,这也是DB中就会有一张中间表,如果在一对多时,不想要这中间,可以使用@JoinColumn(name='groupid')在一的那方的get集合上。如果在xml,那么再group.hbm.xml中用<set name='users'><key column='groupid'><one-to-many class="com.wt.users">
26.多对一或一对多双向关联,在两方中都会有对方的引用且一的那方中有@onetomany且有mappedBy="group"多的那方有many-to-one.
27.多对多的单向关联,一个老师多个学生,一个学生对应多个老师,在teacher类中有student中的set,get方法且在get方法上有@ManytoMany用<set name="student" table='t-s'><key column='teacher-id'></key><many-to-many class="....student" column="student_id">
28.多对多的双向关联在teacher中有set集合的student的,有对应的set,get方法在student类中也有set类型的Teacher的get,set方法且都有@manytomany且在student类中的get方法上有mappedBy用xml时,两个hbm.xml文件中有<set和many-to-many>
29.一对多的话,关联关系有多的那方指定,关联关系: 在many那方中的@manytoone(cascade=(cascadeType.ALL))(这个设置是对cud的,若为r的话,可以用fetch)而(cascade就是为级联,这样的话,在many那方有变动的话,则one的那方也就会变动的,manytoone当进行查询时,可以通过many那方默认自动的将一的那方取出如:
user s=session.get(use.class))可以将group中的记录取出。
当在一的那方取值时,即group中取值的话,默认不会将多的那方取出,即user不会被取出,只有要一的那方group类中的时用@fetch=FetchType-GAGER才会将多的那方取出,才会将user取出。
来源:https://www.cnblogs.com/wangtao-bgs/p/6486559.html