实体类规范
- 提供无参构造方法
- 成员变量私有化 提供get/set方法
- 基本数据类型尽量使用包装类型(可以多表示一个值null 例如考试分数 缺考和0分)
- 实体中必须要提供一个与表中的主键对应的属性id
hibernate是通过主键来区别对象是否相同- 不要使用final修饰实体类(代理对象是要继承该类的)
主键类型
- 自然主键
业务逻辑中本身存在的不能重复的字段设为主键- 代理主键(常用)
自定义一个和业务本身没有关系的字段 设为主键
一般我们这样定义
< generator class=”native”> < /generator>
还可以使用以下几种主键生成策略
identity:主键自增 由数据库来维护主键 录入的时候不需要指定主键
increment:主键自增 由hibernate来维护主键 每次插入前会先查询表中 id最大值 +1 作为新主键 效率不高 每次都要查询 如何10个人同时要保存 可能会出现线程问题
sequence:Oracle中的主键生成策略 序列
hilo:高低位算法(数据库中的主键自增算法原理) 由hibernate来维护主键
native:hilo + sequence + identity 自动三选一 检测你是什么数据库
hibernate 的三种状态
1.瞬时态 没有id 没有和session关联
2. 持久态 有id 有关联
3. 游离态 有id 没有关联
代码示例:
@Test
public void fun5() {
// 获取session
Session session = HibernateUtils.getSession();
// 开启事物
Transaction transaction = session.beginTransaction();
// 包裹语句
User user = new User(); // 瞬时态 无id session中的缓存无关联
user.setId(1); //游离态 有id 无联系
// 从数据库返回结果集 是保存进 缓存和快照中
// updata 时 是这个要更新的对象放入缓存中(跟快照没关系)
session.update(user); // 持久态 有id 有联系
// get查询时 去缓存中查找 看有没有该id的对象
User u = session.get(User.class, 1);
// 提交事物
// 当事物提交的时候 hibernate 会对比快照和缓存中的对象是否相同
// 不相同 会把缓冲中的对象 同步到数据库
transaction.commit();
// 关闭session
session.close(); // 游离态 有id 没关联
}
一级缓存与快照
缓存原理图解:
缓存测试:
@Test
public void fun3() {
// 获取session
Session session = HibernateUtils.getSession();
// 开启事物
Transaction transaction = session.beginTransaction();
// 包裹语句
User user = session.get(User.class, 1);
User user2 = session.get(User.class, 1);
User user3 = session.get(User.class, 1);
User user4 = session.get(User.class, 1);
User user5 = session.get(User.class, 1);
System.out.println(user2 == user5);
// 提交事物
transaction.commit();
// 关闭session
session.close(); // 游离态 有id 没关联
}
// 这里输出 只输出一条查询语句 第二个输出为true
// 根据上图 原理 我们可以看出 第一次 hibernate 和 数据库之间会产生关联
// 并且在返回的结果集中 hibernate 将结果集封装为一个对象 存放在缓存中
// 然后将缓存返回给程序 当第二个语句执行的时候 hibernate 会去缓存中根据id来查询
// 发现匹配成功就直接返回缓存中的对象 hibernate之所以会这样写 是为了提高程序的运行效率 和减少资源浪费
快照原理图片:
代码示例:
@Test
public void fun4() {
// 获取session
Session session = HibernateUtils.getSession();
// 开启事物
Transaction transaction = session.beginTransaction();
// 包裹语句
User user = session.get(User.class, 1);
user.setUsername("james");
user.setUsername("Miku");
// 提交事物
transaction.commit();
// 关闭session
session.close(); // 游离态 有id 没关联
}
// 这里会输出 一条查询语句 和一条修改语句
// 首先我们修改的数据在什么时候进行更改的 ! 是在commit的时候才会进行修改
// 那么commit的时候系统会做什么操作呢?
// 首先系统会根据ID 判断缓存中的对象是否和快照一样 不一样会将缓存中的数据更新到数据库 一样就不做操作
事务的隔离级别
< property name=”hibernate.connection.isolation”>4< /property>
通过hibernate 来设置事物的隔离级别
1.脏读
2.可重复读
3.幻读
READ UNCOMMITTED 读未提交 123 1
READ COMMITTED 读已提交 23 2
REPEATABLE READ 可重复读 3 4
SERIALIZABLE 串行化(只能一个一个访问) 8
设置事物的隔离级别(etc文件中)
隔离级别是用 1个字节存储的 0001 0010 0100 1000
hibernate.connection.isolation 1|2|4|8
获取当前session
需要在hibernate.cfg.xml 中设置才能实现
< property name=”hibernate.current_session_context_class”>thread< /property>
hibernate 中的查询
HQL 查询
@Test
public void fun1() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
String hql = "from User";
Query query = session.createQuery(hql);
// 单数据 使用uniqueResult() 多数据使用list
// User user = (User) query.uniqueResult();
List<User> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
问号?占位符
@Test
public void fun2() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
String hql = "from User where id = ?";
Query<User> query = session.createQuery(hql);
// 给语句中的?赋值 第一个参数 是从零开始
query.setParameter(0, 2);
List<User> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
冒号:占位符
@Test
public void fun3() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 冒号后面 相当于给这个冒号占位符 起了个别名
// 注意:冒号后面不要加空格
String hql = "from User where id =:w";
Query<User> query = session.createQuery(hql);
query.setParameter("w", 1);
List<User> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
分页查询
@Test
public void fun4() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
String hql = "from User";
Query<User> query = session.createQuery(hql);
// 设置起始 和 最大显示
query.setFirstResult(2);
query.setMaxResults(2);
List<User> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
无语局查询
@Test
public void fun6() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
// 添加一个查询条件 Restrictions.eq 等于
Criteria add = criteria.add(Restrictions.eq("id", 2));
List<User> list = add.list();
System.out.println(list);
transaction.commit();
session.close();
}
原生sql 查询 返回的结果 跟对象没有关系
@Test
public void fun8() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
String sql = "select * from user where id = ?";
Query query = session.createSQLQuery(sql);
query.setParameter(0, 3);
// 一条记录就是一个 Object[]
Object[] object = (Object[]) query.uniqueResult();
for (Object object2 : object) {
System.out.println(object2);
}
transaction.commit();
session.close();
}