一、入门
1、对于持久化类的唯一标识,我们通常不会操作,因此它的setter方法的访问级别应该声明private,当对象被保存的时候,只有hibernate可以分它分配值。
2、持久化类都要求有无参的构造器,hibernate必须使用java反射机制来创建对象。构造器的访问级别可以是private,然后当生成运行时代理的时候则要求使用至少是package级别的访问控制,这样在没有字节码指令的情况下,从持久化类里获取数据会更有效率。
3、generator指定了标识符生成策略,指定native表示根据已配置的数据库自动选择最佳的标识符生成策略。hibernate支持由数据库生成,全局唯一性和应用程序指定这些策略来生成标识符。
4、hibernate映射类型,能把Java数据类型转换到SQL数据类型,反之亦然。如果没有设置type属性,hibernate会试着去确定正确的转换类型和它的映射类型。在某些情况下这个自动检测机制不会产生你所期待或需要的缺省值。比如date属性,hibernate无法知道这个属性应该被映射成: Sql date或timestamp, 还是time字段。
5、session在第一次被做的时候,即第一次调用sessionFactory.getCurrentSession()的时候,生命周期就开始。然后它被hibernate绑定到当前线程。当事务结束的时候,不管是提交还是回滚,hibernate会自动把session从当前线程剥离,并且关闭它。
6、自动脏检查:没有显示的update()或save(),hibernate也会自动检测到集合已经被修改并需要更新回数据库;
7、只要处于持久化状态,就是被绑定到某个hibernate的session(被加载或者保存)上,修改对象属性,hibernate会监视任何修改并在后台隐式写的方式执行sql.
8、清理缓存flushing:在单元操作结束的时候,同步内存状态和数据库的过程。
9、可以在session以外修改不是处在持久化状态下的对象(脱管状态,以前曾经被持久化),然后可以重新持久化,对它所做的任何修改都会被保存到数据库里。
10、inverse映射属性:hibernate没有足够的信息去正确地执行insert和update语句,inverse设置将告诉hibernate忽略关联的这一端,把这端看成是另外一端的一个镜像。在一对多关联中它必须代表多的那端,而在多对多关联中,你可以任意选取一端,因为两端之间没有区别。
二、配置
1、Configuration实例被设计成启动期间对象,一旦SessionFactory创建完成,它就会被丢弃。
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class)
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true");
2、SessionFactory: 当所有映射定义被Configuration解析后,应用程序必须获得一个用于构造Session实例的工厂。这个工厂被应用程序的所有线程共享,hibernate允许应用程序创建多个SessionFactory实例,这对使用多个数据库的应用来说很有用。
SessionFactory sessions = cfg.buildSessionFactory();
3、hibernate.order_updates: 强制Hibernate按照被更新数据的主键,为SQL更新排序。这么做将减少在高并发系统中事务的死锁。取值 true | false
4、hibernate.generate_statistics:如果开启, Hibernate将收集有助于性能调节的统计数据.取值 true | false
三、事务和并发
1、Hibernate直接使用JDBC连接和JTA资源,不添加任何附加锁定行为。
2、Hibernate不锁定内存中的对象,应用程序会按照数据库事务的隔离级别规定的那样操作。有了Session,使得hibernate通过标识符查找,和实体查询提供了可重复的读取功能,Session同时也是事务范围内的缓存。
3、除了对自动乐观并发控制提供版本管理,针对行级悲观锁定,hibernate也提供辅助API,它使用了SELECT FOR UPDATE的sql语法。
4、数据库事务应该尽可能的短,降低数据库中的锁争用。 数据库长事务会阻止你的应用程序扩展到高的并发负载。
5、Session 缓存了处于持久化状态的每个对象(Hibernate会监视和检查脏数据)。Session载入过多的数据,占用的内存会一直增长,直到抛出OutOfMemoryException,一个解决办法是调用clear()和evict()来管理Session的缓存,如果需要大批量数据操作,最好考虑使用存储过程。
6、结束session四个阶段:同步session(flush,刷出到磁盘),提交事务,关闭session,处理异常
7、悲观锁定:类LockMode 定义了Hibernate所需的不同的锁定级别。
当hibernate更新或者插入一行记录的时候,锁定级别自动设置为LockMode.WRITE;
当用户显示 的使用数据库支持的sql格式select for update执行sql,锁定级别设置为LockMode.UPGRADE;
当用户显示 的使用数据库支持的sql格式select for update nawait执行sql,锁定级别设置为LockMode.UPGRADE_NOWAIT;
当hibernate在可重得读或者是序列化数据库隔离级别下读取数据的时候,锁定模式自动设置为LockMode.READ,这种模式也可以通过用户显示指定进行设置
LockMode.NONE代表无需锁定。在Transaction结束时,所有的对象都切换到该模式。与session相关联的对象通过调用update()或者是saveOrUpdate()脱离该模式。
8、显示指定LockMode: 调用session.load()时候可指定;调用Session.lock();调用Query.setLockMode().
9、如果在UPGRADE或者UPGRADE_NOWAIT锁定模式下调 用Session.load(),并且要读取的对象尚未被session载入过,那么对象 通过SELECT ... FOR UPDATE这样的SQL语句被载入。如果为一个对象调用 load()方法时,该对象已经在另一个较少限制的锁定模式下被载入了,那 么Hibernate就对该对象调用lock() 方法。
四、批量插入
1、批量插入
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20,与JDBC批量设置相同
//flush a batch of inserts and release memory:
//将本批插入的对象立即写入数据库并释放内存
session.flush();
session.clear();
}
}
tx.commit();
session.close();
2、批量更新,使用 scroll() 方法以便充分利用服务器端游标所带来的好处
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( ++count % 20 == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
3、StatelessSession (无状态session)接口
作为选择,Hibernate提供了基于命令的API,可以用detached object的形式把数据以流的方法加入到数据库,或从数据库输出。StatelessSession没有持久化上下文,也不提供多少高层的生命周期语义。特别是,无状态session不实现第一级cache,也不和第二级缓存,或者查询缓存交互。它不实现事务化写,也不实现脏数据检查。用stateless session进行的操作甚至不级联到关联实例。stateless session忽略集合类(Collections)。通过stateless session进行的操作不触发Hibernate的事件模型和拦截器。无状态session对数据的混淆现象免疫,因为它没有第一级缓存。无状态session是低层的抽象,和低层JDBC相当接近。
StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
session.update(customer);
}
tx.commit();
session.close();
注意在上面的例子中,查询返回的Customer实例立即被脱管(detach)。它们与任何持久化上下文都没有关系。StateessSession 接口定义的insert(), update() 和 delete()操作是直接的数据库行级别操作,其结果是立刻执行一条INSERT, UPDATE 或 DELETE 语句。
---学习来源https://hibernate.net.cn/