使用Hibernate最大的目的就是对数据库进行crud操作。在讲解之前,我们需要了解持久化以及持久化对象的三种状态。
持久化就是把内存中的数据永久的存储到数据库中
持久化类就是Java类与数据库建立的一种映射关系,并把这个类称做持久化类。实际上,就是一张数据表中的字段与类中的属性字段相对象的类。
1.需要提供无参数的构造方法
因为Hibernate通过反射机制生成类的实例
2.需要私有属性,并提供对应的get和set方法
因为Hibernate底层会对获取到的数据惊醒封装
3.属性尽量使用包装类类型
区分空和null
4.类中必须存在一个唯一标识 OID与表中的主键对应
Hibernate利用这个这个唯一标识来区分内存中是否是同一个持久化类
5.不要使用final修饰类
因为Hibernate有加载延迟机制,这个机制会产生代理对象。代理对象是通过字节 码增强技术来完成的,其实就是通过产生子类的方式,如果使用final修饰持久化类,这个机制就会失败。加载延迟机制是一种优化的手段。
主键的类型
- 自然主键
把具有业务含义的字段作为主键,称为自然主键。比如,客户的姓名(必须保证姓名不重复,唯一,非空),这类主键往往会因为业务的改变重新设计表,造成数据库维护困难。- 代理主键
把具有非业务字段作为主键,称为代理主键。通常是ID,类型是整数类型(比字符串节省空间)- Hibernate提供了几个内置主键生成策略
1.increment:用于short int long类型。以自动增长的方式,每次增量是1。
2.identity:采用底层数据库本身提供的主键生成标识,前提是数据库支持自动增长的类型。
3.sequence:Hibernate根基底层序列生成标识符,前提是数据库支持序列。
4.native:根据底层数据库生成能力来判断生成identity、sequence、hilo中的一种。适合跨数据库开发。
5.uuid:采用128位uuid算法生成标识符
6.assigned:由Java程序负责生成标识符。如果不指定id的generator属性,默认使用该属性。适合自然类型。
下面通过列举例子来说明上述内容
@Test
public void demo() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 瞬时态,此时没有OID,也没有与session关联
User user = new User();
user.setUsername("robin");
Serializable save = session.save(user); // 持久态
transaction.commit();
session.close();
sessionFactory.close();
// 托管态,此时session关闭,没有与session关联,但是有OID
System.out.println(user);
}
转换关系
瞬时态
1.瞬时态 -- 持久态
调用save()或者saveOrUpdate()
2.瞬时态 -- 托管态
为瞬时态添加 OID
持久态:可以从Session get() load()方法获取,或者Query对象等
1.持久态 -- 瞬时态
session.delete()删除持久态化对象
2.持久态 -- 托管态
session.evict()、clear()、close()方法。evict()用于清除一级缓存中的某一个对象,clear()用于清除一级缓存中的所有对象, close()关闭session,并且清除一级缓存。
托管态
1.托管套 -- 持久态
执行update()、saveOrUpdate() lock()等
2,托管态 -- 瞬时态
把对象的OID设置为null
依赖Hibernateu一级缓存
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
User user = session.get(User.class, 2);
user.setUsername("Robin");
// session.update(user); 这句话可以省略,因为持久态的对象会自动更新数据库
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
}
缓存是计算机为了提高读取速度而设计的。通常介于应用程序和永久性存储介质之间。提高应用的运行能力,通常是内存。
Hibernate缓存分为一级缓存和二级缓存(redis替代),一级缓存是Hibernate内置缓存,不能删除。
Hibernate一级缓存实际上就是session缓存。Session缓存是一个内存空间,存放相互管理的Java对象。在使用对象查找的时候,会使用OID在Hibernate一级缓存中进行查找,如果查找到了,就返回此对象,否则,就会去数据库查找与之相同OID的对象。
只要session实例没有结束生命周期,存放在它上面的缓存也不会消失。
一级缓存的特点
当应用程序调用Session的save()、update、saveOrUpdate()的时候,Session缓存中没有相应的对象的时候,Hibernate会自动的从数据库中提取对应的数据加载到一级缓存中
当应用程序调用Session load()、get(),以及Query中的、list()、iterator()的时候,Hibernate首先会从以及缓存中寻找对象,如果存在则不需要去数据库中查找。,如果没有则从数据库中获取并加载到一级缓存中
当调用Session.close()的时候,session缓存会被清空。
观察控制台输出的SQL语句
@Test
public void demo() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
/**
* 查询两次
*/
/**
* 第一次执行你会查询数据库
* 第二次查询只会去缓存中寻找
*/
User user = session.get(User.class, 1);
User user1 = session.get(User.class, 1);
transaction.commit();
session.close();
sessionFactory.close();
}
Hibernate向一级缓存中存储数据的时候,会拷贝一份数据放在Hibernate快照区,当使用事务提交之后,会根据OID比较一级缓存中的数据和快照区中的数据是否一致,如果不一致,则执行更新操作,并且同步快照区的数据,否则则不执行任何操作。
在业务层处理事务的方法
1.在业务层中获取session,把它传递给持久层
2.使用ThreadLocal将业务层获取到的session绑定到当前线程中去。然后到业务层获取的时候获取当前线程的session.
<property name="hibernate.current_session_context_class">thread</property>
sessionFactory.getCurrentSession()
可以不需要关闭session,线程结束之后会自动关闭
thread: Session对象的生命周期与本地线程绑定
jta:Session对象的生命周期与JTA事务绑定
managed:Hinernate委托程序来管理Session对象的生命周期
Query是面对对象的Hibernate查询操作。通过session.createQuery(),传递一个HQL语句,获取Query对象。
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* 创建Query
* 调用对象的方法
*/
Query query = session.createQuery("from User");
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
Criteria是一个完全面对对象,可扩展的条件查询API,它不需要考虑数据库底层的实现,以及SQL语句的编写。它是Hibernate核心查询对象,又称为OBC(Object By Criteria)
@Test
public void demo() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* Criteria
* 创建Criteria对象
* 调用方法
*/
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
SQLQuery用来接收SQL语句,需要我们手动封装数据
@Test
public void demo03() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
/**
* 对象
* 调用方法
*/
String sql = "select * from `tb_user`";
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.addEntity(User.class);
List<User> list = sqlQuery.list();
// List<Object[]> list = sqlQuery.list();
// for (Object[] user : list) {
// System.out.println(Arrays.toString(user));
// }
for (User user : list) {
System.out.println(user);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。