hibernate笔记

1,connection.driver_class com.mysql.jdbc.Driver中配置属性时,可以不写hibernate
2,hibernate.connection.url jdbc:mysql:///test  主机时可以这样写


3,显示创建数据库表过程:show create table student;
   显示数据库所有引擎:show engines;


4,java类默认的构造方法(必须的)
  id可选
  实体类最好不要有final限制,(因为不能继承,懒加载特性就不能完成了)


5,Configuration cfg = new Confguration().configure();
  SessionFactory sf = cfg.buildSessionFactory();
  这段代码只会执行一次


6,构造方法如果是private,则这个类不能new出对象


7,所有的src目录最终会编译到classPath目录下去


8,session和jdbc中的Connection是等价的,和http的session没有关系


9,Class userClass = User.class;(get load时用到) Class里边包含User的所有信息
  User user = (User)session.get(User.class,id);  这里User.class需要找到映射的哪个文件,然后从哪个表中取值


10,get():立即访问数据库
   load():不会立即访问数据库,当第一次使用时才会访问数据库,返回的是代理
   load()出来的对象永远都不会为空,因为他会new出一个子类


11,persist()和save()方法相似,不同是没开启事务时不会执行insert语句,save()会,后在回滚
   lock():将数据保存起来并且加上锁


12,游离,持久,脱管三种状态的判断依据(数据库、session)


13,saveOrUpdate():当不知道对象处于什么状态时,使用这个方法,hibernate自行处理,根据id判断


14,hql:hibernate query language  ;  criteria:条件查询,面向对象(hibernate提供的两种查询语言)
   其他操作都可以通过session对象完成


15,hibernate中查询都不会修改数据库,所以可以不使用事务


16,为什么hibernate能够知道映射文件的一个外键等于另一个映射文件的主键?:这是hibernate的默认设置(关联时)


17,如果已经设计好表(关联关系都正确),hibernate启动的时候就不会在创建表,他只从面向对象的角度考虑


18,表或者是映射文件,都是在多的一方定义外键


19,员工的外键=部门的主键;员工的外键和员工的主键一一对应。


20,一对一主键关联:有主对象和从对象


21,一对一外键关联表结构和多对一关联表结构一样,唯一不同是外键值必须唯一。


22,一对一,一对多是通过更新外键建立关联的;多对多是通过在中间表插记录建立关系的.


23,多对多关联中,无论从哪一方导航,只需一次即可,从中间表中可以相互查询。(因为多对多不是通过更新外键维护关系的


,而是往中间表中插入数据维护的,根据主键唯一,所以只能是其中一方来维护关系。)


24,组件关联关系的映射:当有两个实体类想在数据库中保存为一张表,比如一个User类,里边有一个private Name name;
   Name{firstName,lastName},可以用<component>


25,一对一关联关系中,查询主对象时将从对象也查询出来,只执行了一条select语句,其他关联关系都是两条select语句(


默认,可以修改)


26,使用list时,由于有顺序,需要在映射文件中加一个<list-index column="order_col" />,告诉hibernate用那一列来记


住顺序,实体类中没有与之对应的属性,(其他和set一样);如果不需要记住顺序,可以使用<bag></bag>,hibernate特有的,


jdk中没有定义;这时就没有顺序了(使用<bag>和<list>时,实体类中必须对应list)


27,使用map时,映射文件中多了一个<map-key type="string" column="name" /> 对应实体类中Map<String,Object> maps; 


name是key


28,使用数组时,映射文件配置和list一样   对应实体类object[] objs ;


29,集合的使用简单规则:大部分情况下用set,保证顺序用list,想用list又不保证顺序用bag


30,实体类中使用集合时,都必须用集合的接口,否则是不能在hibernate中运行通过的


31,hibernate中的所有集合都重写了jdk中的集合。新的集合都实现了jdk中的接口,功能更为强大 


32,hibernate默认不会保存复杂属性(如果你不同时save),可以在set上修改级联cascade属性值(对主对象做某种操作也要


对级联的从对象做同样的操作,缺省不进行任何级联) 。一般在多对多、多对一不设置级联;在一对一,一对多中设置级联


.


33,inverse,在一对多中,一的一方放弃关系的维护,可以提高效率。(老师记住所有同学的名字很困难,所以就不记了。让


同学记住老师).如果用inverse这个设置,则必须用many.setOne(one),让多的一方维持关联关系。inverse属性只在集合里边


有。inverse不能在有序的集合中使用(list、array):因为它已经放弃了关系的维护,所以他更不可能去维护顺序了。


34,hibernate支持多态的查询。


35,整个继承体系一张表:效率比较高;每增加一个子类,都需要在表中增加一个相应的字段,字段不能有非空约束。
   <discriminator column="type" type="int"/><!--鉴别器-->
   <subclass name="Skill" discriminator-value="1"></subclass>鉴别器属性值,区分不同的类,鉴别器缺省值为类名称,


一个字符串


36,每个子类映射到一张表:效率不高,表结构比较合理。相同属性放在基类中,每个差异属性都新建表。
   <joined-subclass name="Skill" table="skill">
<key column="emp_id"/>主键、外键
<property name="skill"/>
   </joined-subclass>


37,使用load时有懒加载现象(很少使用),可以在load后边初始化代理对象:Hibernate.initialize(obj);访问单个对象的时


候可以这样用,当有关联对象时这样会降低系统的性能,不推荐使用。
   初始化代理相当于从数据库中取出对象信息赋予一个代理对象。所以会发出查询语句


38,懒加载的实现是通过asm.jar和cglib.jar实现的,这两个包可以调用二进制字节码


37.将属性少的类和基类一张表,属性多的类单独一张表。


38,lazy属性作用:设置相关联的对象什么时候抓取。
    lazy属性缺省是proxy(使用代理)|false|true;  
    lazy=proxy:只访问主对象,不访问关联对象;
    lazy=false:同时访问主对象和关联对象;
    lazy=true:


39:fetch属性作用:设置相关联的对象通过什么方式抓取。
   fetch=select(缺省)通过第二次查询抓取;
   fetch=join通过连接表的方式一次将所有数据都查出来;join时懒加载就失效了


40:一对一查询主对象时也会将从对象查询出来,这里hibernate放弃了懒加载;因为person表中没有一个外键,hibernate不


知道是否有idCard这个对象,无法给其赋值,所以干脆从数据库中将其查出来(因为数据量很小)。(如果有外键,肯定有其他


对象与之对应);;一对多时,部门表中也没有外键,却可以实现懒加载?(因为要查询关联的数据量可能很大,hibernate不


想冒险,所以就给关联对象一个代理:个人理解)


41,能够懒加载的对象都是被改写的代理对象,访问这些对象是有限制的。当相关联的Session没有关闭时或初始化这些对象


,可以访问这些懒加载的对象的属性。


42,当访问被代理对象的getId()和getClass()方法时,hibernate不会初始化代理对象,也就是不会访问数据库,因为它本


来就知道。id可以从主对象的外键中获得,Class是new出来的,他知道自己的类型是什么


43,懒加载(相关联对象:复杂属性)是通过代理这种方式实现的,也就是动态生成子类的方式来实现;代理的对象只有被访问


的时候才会去访问数据库,前提必须是还没有关掉相关联的Session。


44,hibernate二级缓存:一级(session内部)、二级(SessionFactory)


45,finally语句:其他语句执行完,无条件执行


46,手工清理缓存:s.evict(obj)清理掉一条记录 ; s.clear()清理掉所有记录


47,使用一级缓存,数据量大时,容易造成缓存溢出.存在时间短暂,session关闭,缓存清除


48,缓存的声明:可以在总配置文件中声明;也可以在映射文件中声明<cache usage="read-write"/>放在id前边


49,缓存的使用步骤:首先使用缓存为真(默认),其次声明一个缓存的实现者(第三方框架),引入第三方缓存配置文件,
   最后声明哪些类需要使用缓存


50,hibernate使用缓存时,先从一级缓存找,找不到再从二级缓存找。


51,配置<property name="generate_statistics">true</property>可以使用hibernate的统计信息
   Statistics st = HibernateUtil.getSessionFactory().getStatistics();//统计信息


52,二级缓存存在时间比较长,只要sessionFactory存在,缓存就存在。


53,一个sessionFactory代表一个数据库,JDBCTransaction只能再一个数据库上操作


54,悲观锁:比如说两个人要修改库中同一条数据,第一个人先读取数据,然后库中加锁,直到更新完成后其他人才能访问此


数据。


55,乐观锁:通过版本号(version)或者时间戳(timestamp)来实现。
    第一个人读取数据是库中版本号为0,取出数据的版本号也是0,修改之后先比较两个版本号是否一致,一样则更新数据


,然后库中版本号加1。第二个人更新后保存时数据版本号和库中不一致,所以更新失败。(两个人同时取出数据,先提交者


成功)。只需在映射文件中id后边配置<version name="ver" /> (常用)ver为实体的一个属性,用于实现乐观锁用。
也可以用时间戳实现<timestamp name="xx" /> 


56,映射文件的类型:type,可以是hibernate类型(都是小写的),也可以是java类型(必须写全包名),type类型一般不需


要人为配置。


57,flush()方法:一级缓存与数据库同步时候用,不建议开发人员使用。hibernate会择时调用


58,对于持久态的对象更新的时候,是不需要调用s.update()方法,hibernate可以自动检测到自动更新。


59,hibernate3.0以前的版本对于批处理更新数据需要把所有数据都取出来一条一条的更新;
   3.0以后的版本新增了对批处理的支持,只需Query q = s.createQuery("update u set birthday = :bd from User u");
   q.executeUpdate();//注意这条语句会将所有的一级缓存和二级缓存都清空。


60,针对id查询的时候,尽量用get或load;使用query查询的时候不会从缓存中查找,而是直接从库中查找。get和load会首


先查询缓存


61,避免N+1: (1)将fetch更改为join;(2)利用二级缓存


62,openSessionInView():缺点将事务和Session的周期延长了,对于并发处理,会造成比较大的影响


63,多使用运行时异常(从RuntimeException继承),少使用编译时异常


64,hibernate最佳实践:
    1、使用Component(细颗粒度),简化实体类;
    2、映射文件用没有逻辑意思的id为主键;
    3、为每个持久类定义一个映射文件;
    4、实体类与映射文件放一块;
    5、配置文件多使用占位符;
    6、没id查询条件是使用:var,少使用?
    7、尽量不要使用flush();
    8、使用脱管对象(从库中取出来要关闭session)
    9、异常发生时必须回滚、关闭session
    10、偏爱双向关联(一对多、多对多慎重考虑)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值