实体类规范
- 为实体类提供有参和无参构造方法;
- 将成员变量私有化,提供get/set方法。
- 基本数据类型尽量使用包装类型(可以表示一个值null )
- 实体类中必须要有一个与表中主键对应的Id, hibernate是通过主键来区别对象是否相同。
- 不可以使用final修饰实体类。
主键的类型
- 自然主键,例如 身份证号,没人只有一个唯一的。
- 代理主键(常用),找不到符合业务字段的主键就自己设置一个没有任何意义的Id列来充当主键,叫做代理主键。
hibernate中主键的生成策略
- identity:主键自增,有数据库维护主键,录入时不需要制定主键,
<generator class="identity"></generator>
@Test
public void fun1() {
//获取session
Session session = HibernateUtil.getSession();
//开启事务
Transaction transaction = session.beginTransaction();
//包裹语句
//不需要设置主键,数据库会自动添加主键
User user = new User();
user.setUsername("wl");
user.setPassword("123");
session.save(user);
//提价事务
transaction.commit();
//关闭session
session.clear();
}
2.increment 主键自增 由hibernate维护主键id 每次插入数据都会先查询最大的主键,然后加1 来设置主键
<generator class="increment"></generator>
3.sequence :Oracle 中的主键生成策略 序列。
4.hilo:高低位算法(数据库中的主键自增算法原理) 也是由hibernate维护
5.native:hilo+identity+sequence 三选一,系统会检测你的数据库,来确定使用哪个(常用)。
6.uuid:全球不重复的值并且这个值是一个字符串,但是这个主键必须是字符串类型
7.assigned:有程序员自己管理的主键;
三种状态
- 瞬时态:没有id 没有上session缓存
- 持久态:有id 有session缓存
- 游离态:有id 没有session缓存
@Test
public void fun2() {
//获取session
Session session = HibernateUtil.getSession();
//开启事务
Transaction transaction = session.beginTransaction();
//包裹语句
// 瞬时态 没有id 没有和session关联
User user = new User();
user.setUsername("wl");
user.setPassword("123");
//持久态 有id 有和session关联
session.save(user);
//提价事务
transaction.commit();
//关闭session
//游离态有id没有关联
session.clear();
}
结论:将我们想要同步到数据库的数据 所对应的对象转化成持久态。
一级缓存和快照
一级缓存
使用hibernate进行查询的时候,将查询结果放置到session的一级缓存中,在一级缓存中存在对象,对象使用属性的OID的值进行区分,此时再使用相同的OID进行查询的时候,首先会在session一级缓存中进行查找是否存在相同的OID。
1. 如果存在相同的OID,此时不再查询数据库,而是直接使用一级缓存中存在的对象
2. 如果没有存在相同的OID,此时再查询数据库,将查询得到的结果数据再放置到session一级缓存中
3. 目的:减少访问数据库的次数,提高效率。
快照
使用id进行查询数据库,将查询得到的结果放置到session一级缓存中,同时复制一份数据,放置到session的快照中
当使用tr.commit()的时候,同时清理session的一级缓存(flush)
当清理session一级缓存的时候,会使用OID判断一级缓存中对象和快照中的对象进行比对。
1. 如果2个对象(一级缓存的对象和快照的对象)中的属性发生变化,则执行update语句,此时更新数据库,更新成一级缓存中的数据。
2. 如果2个对象中的属性不发生变化,此时不执行update语句
3. 目的:确保和数据库中的数据一致。
事务的隔离级别
通过hibernate设置事务的隔离级别
1.脏读
2.可重复读
3.幻读
READ UNCOMMITTED 读未提交 123 0001
READ COMMITTED 读已提交 23 0010
REPEATABLE READ 可重复读 3 0100
SERIALIZABLE 串行化(只能一个一个访问)1000
设置事物的隔离级别(etc)
specify a JDBC isolation level
hibernate.connection.isolation 1|2|4|8
隔离级别使用一个字节存储的
<property name="hibernate.connection.isolation">4</property>
三种查询
- HQL查询
单数据查询:uniqueResult接收结果
@Test
public void fun1() {
String hql = "From User Where id = 2";
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
Query query = session.createQuery(hql);
// 预见结果(单数据使用uniqueResult)
User user = (User) query.uniqueResult();
System.out.println(user);
beginTransaction.commit();
session.close();
}
多数据: list集合接收
@Test
public void fun2() {
String hql = "From User";
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
Query query = session.createQuery(hql);
// 预见结果(单数据)
// User user = (User)query.uniqueResult();
// System.out.println(user);
List<User> list = query.list();
System.out.println(list);
beginTransaction.commit();
session.close();
}
HQL 查询 问号占位符
@Test
public void fun3() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
String hql = "from User where id= ? username=?";
Query query = session.createQuery(hql);
// 相当于给语句中的?赋值从0开始
query.setParameter(0, 2);
// query.setParameter(1, "w");
// List<User> list = query.list();
User user = (User) query.uniqueResult();
System.out.println(user);
beginTransaction.commit();
session.close();
}
HQL查询 冒号占位符
@Test
public void fun4() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
String hql = "from User where id=:ww";
// 冒号后面相当于给冒号占位符替别名
// 冒号后面不要加空格
Query query = session.createQuery(hql);
// 直接使用别名赋值
query.setParameter("ww", 1);
System.out.println(query.uniqueResult());
beginTransaction.commit();
session.close();
}
分页查询
@Test
public void fun5() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
String hql = "from User ";
Query query = session.createQuery(hql);
// 设置起始和最大显示
query.setFirstResult(3);
query.setMaxResults(2);
// 接受结果
List list = query.list();
System.out.println(list);
beginTransaction.commit();
session.close();
}
2.无语句查询
/*
* 无语句查询
*/
@Test
public void fun6() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
List list = criteria.list();
System.out.println(list);
beginTransaction.commit();
session.close();
}
无语句条件查询
@Test
public void fun7() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
// 添加一个查询条件
criteria.add(Restrictions.gt("id", 6));
User user = (User) criteria.uniqueResult();
System.out.println(user);
beginTransaction.commit();
session.close();
}
无语句按条件查询 查询总行数
@Test
public void fun8() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.rowCount());
// 返回值是数的通常使用Long接受
Long l = (Long) criteria.uniqueResult();
System.out.println(l);
beginTransaction.commit();
session.close();
}
3.SQL查询
@Test
public void fun9() {
Session session = HibernateUtil.getSession();
Transaction beginTransaction = session.beginTransaction();
String sql = "select * from user where id = ?";
Query query = session.createSQLQuery(sql);
query.setParameter(0, 2);
//一条记录就是一个object[]
Object[] objects = (Object[])query.uniqueResult();
for (Object object : objects) {
System.out.println(object);
}
// List<Object[]> list = query.list();
// for (Object[] objects : list) {
// System.out.println(Arrays.toString(objects));
// }
beginTransaction.commit();
session.close();
}