- --hibernate.cfg.xml
- *该文件一般位于src下面,当然可以任意放
- *文件具体内容
- <hibernate-configuration>
- <session-factory>
- <property name="key">value</property>
- <mapping resource="xxx/xxx/xxx"/>
- </session-factory>
- </hibernate-configuration>
- --xxx.hbm.xml
- *该文件一般和实体类放在一起,其中hbm是hibernate mapping的简写形式
- *文件具体内容
- <hibernate-mapping>
- <class name="类完整路径" table="表名">
- <id name="属性名" colunm="列名">
- <generator class="主键生成策略"/>
- <id>
- <property name="属性名" colunm="列名"/>
- </class>
- </hibernate-mapping>
- --使用hbm2ddl工具导出数据表
-
- org.hibernate.cfg.Configuration cfg=neworg.hibernate.cfg.Configuration().configure("如果改名的话,可以写在里面");
-
- org.hibernate.tool.hbm2ddl.SchemaExport export=neworg.hibernate.tool.hbm2ddl.SchemaExport(cfg);
-
- export.create(是否将生成的语句打印到控制台,是否执行导出);
- --一次简单的保存数据过程
- org.hibernate.cfg.Configuration cfg=neworg.hibernate.cfg.Configuration().configure();
- SessionFactory sessionFac=cfg.buildSessionFactory();
- Session session=null;
- try{
- session=sessionFac.openSession();
- session.beginTransaction();
- User user=new User();
- session.save(user);该方法抛出HibernateException
- session.getTransaction.commit()
- }catch(Exception e){
- session.getTransaction.rollback();
- }finally{
- if(session!=null){
- if(session.isOpen()){
- session.close();
- }
- }
- }
- --hibernate常用接口
- *可以使用的数据源
- JDBC,常用的配置方式就是默认使用JDBC的连接方式的,该方式支持本地事务,不支持分布式事务
- JNDI, Java Name And Directory Interface(java名称和目录接口),每一个字符串对应到一个对象,相当于注册表一样,可以管理对象,以目录层次的方式管理注册上来的对象,解耦嘛,通过名称就能获取对象,而不不要知道具体对象的实现细节。可以通访问JNDI数据源的方式获取连接池中的连接
- JTA,Java Transaction Api,java 事务AIP,分布式事务的支持,因为hibernate.cfg.xml可以配置多个session-factory
- 用容器的方式管理分布式数据库的事务,使用两阶段提交协议来实现分布式事务的原子性
- *无侵入性的接口
- Configuration,用于读取hibernate.cfg.xml配置文件
- SessionFactory, 每一个SessionFactory对应一个数据库实例,它是重量级的,创建很耗时,所以一般一个程序只需要创建一份实例就行了,由于推荐只有一份实例,所以他是线程安全的,由于他对应的整个数据库,所以它中间管理的缓存能被多个session实例共享,就是说它维护二级缓存
- Session,一般每一次请求对应一个session,它是通过SessionFactory创建的,非线程安全,所以注意同步,自身管理它的事务,自身管理他的connection,并和一级缓存息息相关,用一套很复杂的机制管理对象的状态
- 只有用的时候它才从连接池获取connection对象,而不是open之后就打开连接
- 虽然我们配置的JDBC方式,但hibernate内部默认实现了连接池的,所以不会有多大的性能问题,就用常规的配置方法就够了
- session用完之后必须关闭
- Transaction,用于管理事务的接口,和session接口密切相关
- Query,hibernate中实现查询的接口,支持普通SQL语句和HQL(hibernate query language)语句(HQL也是adapter设计模式的运用,首先这套语法操作对象,适合于任何数据库,就是对sql语句功能的扩展的适配而已)
- UserType,扩展转换器使用的接口,和struts的Convert机制一致
- Interseptor,拦截器,类似于servletAPI中的Filter,能拦截到对象修改的事件,比如保存之前,修改之后的事件拦截(简单的说就是状态改变的事件会被拦截,可以再三种状态的转换过程中处理一些事情)
- *有侵入性的接口(不建议使用)
- Lifecycle,和拦截器差不多,比如保存之前,修改之后之类的事件拦截(简单的说就是状态改变的事件会被拦截,可以再三种状态的转换过程中处理一些事情)
- Validatable,类似于struts中actionForm中的validate,没多大意义,因为一般情况下都是只有安全的数据才能进入持久层,没必要再验证了嘛
-
- --持久对象的生命周期(Persistent Object)
- 在session的管理下对象的三种状态
- 瞬时(Transient Object) 没有被session管理,并且数据库中没有对应的记录(对应是通过主键来判断的)
- 刚new出来的对象,被session.delete()的持久化对象
- 持久(Persistent Object) 被session管理,并且数据库中有对应的记录,管理意味着对象的引用地址被session持有,简单说就是引用地址放在session中维护的缓存里面了,当然不会被GC回收
- 从数据库中get(),load(),find(),iterator().list()出来的对象,因为都是从数据库中本生就存在的记录读取出来,当然是持久的了
- 当瞬时对象调用,save(),或者saveOrUpdate(),没有则插入,有则修改这些方法之后,成为持久对象
- 当离线对象,调用它的update,saveOrUpdate,方法后成为持久对象
- 离线(Detathed Object) 没有被session管理,但是数据库中有对应的记录
- 当持久对象被evict(),或者session.close(),session.clear()之后,持久状态变为离线状态,因为session已经关闭,或者session的缓存已经不存在了
- 注意三者之间会智能的转换,没有绝对的定义
- 比如刚new出来的对象,但是通过ID可以判断他在数据库中有与之对应的记录,所以可以直接调用他的delete方法,在调用的时候实际上它已经是持久对象了
- 刚new出来的对象,可以直接调用他的saveOrUpdate,或者update方法,如果在数据库有对应的记录,实际上将它看成离线状态了
- 很简单,最重要的是是否有与之对应的记录,是否被session管理他会自动判断
-
- --请写一个单例
- public class Singleton {
- private static Singleton singleton=null;
- private Singleton(){}
- public synchronized static Singleton getInstance(){
- if(singleton==null){
- return new Singleton();
- }else{
- return singleton;
- }
- }
- }
-
- --JUnit
- *单元测试工具,有了他就可以以方法作为单元进行测试,而不需要每次都依赖用main()方式测试
- *首先需要继承junit.frameword.TestCase类,方法名以"test"开头,必须为public void,方法不能有参数
- *assertEquals(),断言方法实现测试,setUp()在类初始化的时候执行,tearDown()方法在类消亡之前调用
-
- --session接口的基本用法和该接口实现类生命周期
- *通常情况下让session和事务的生命周期一致是比较好的方式
- *实例分析一
- User user=new User();
- session1.save(user);
- user.setName("xxx");
-
- session1.getTranaction().commit();
- session1.close();
- user.setName("xxx")
- session2.update(user);
- session2.getTransaction().commit();
- session2.close();
- *实例分析二
- User user=session.get(User.class,"存在的ID");
- 发出sql语句,并返回User对象的引用
- User user=session.load(User.class,"存在的ID");
- 不发出sql语句,返回User的继承类(cglib帮忙实现的),注意JDK的动态代理需要目标对象实现接口,而cglib不需要,它是用生成继承类的方式实现代理的
- 当第一次使用到该代理的getXXX()方法的时候,代理类会检查成员变量target是否为空,如果为空则发出sql语句,填充数据
- User user=session.get(User.class,"不存在的ID");
- 发出sql语句,返回null
- User user=session.load(User.class,"不存在的ID");
- 不发出sql语句,返回User的继承类(cglib帮忙实现的)
- 当第一次使用到该代理的getXXX()方法的时候,代理类会检查成员变量target是否为空,如果为空则发出sql语句,如果从数据库中没有找到对象则抛出ObjectNotFoundException
- 就算class上的lazy=false也会抛出该异常
|