Java mac idea hibernate的使用02

1. 持久化类创建

1.1 注意事项

  1. 持久化类需提供无参构造
  2. 成员变量私有,提供公有的set/get方法访问
  3. 持久化类中的属性尽量使用包装类
  4. 持久化类需提供oid,与数据库中的主键列对应
  5. 不要用final修饰class,因为cglib代理(继承代理)

1.2 主键类型

  1. 自然主键(少见)
    表的业务列中,有某业务列符合“必须有且不重复的特征”,该列可作为主键列使用。
    assigned:自然主键生成策略。hibernate不会管理主键值,由开发人员自己录入

  2. 代理主键
    表的业务列中,没有有某业务列符合“必须有且不重复的特征”时,创建一个没有业务意义的列作为主键。

generator:主键生成策略,每条记录录入时,主键的生成规则

identity: 主键自增,由数据库维护主键值,录入时不需要指定主键

increment(存在线程安全问题): 主键自增,由hibernate维护,每次插入前会先查询表中id的最大值,+1作为新主键,开发时不使用

hilo:高低位算法,主键自增,由hibernate维护,开发时不使用

sequence:oracle中的主键生成策略

native:identity+ hilo + sequence 自动三选一策略

uuid:产生不重复的随机字符串作为主键,主键类型必须为string类型

2. hibernate中对象的状态

2.1 hibernate中对象的三种状态

  1. 瞬时状态:没有id,没有与session关联
  2. 持久化状态:有id,与session关联
    3.游离状态|托管状态:有id,没有与session关联
@Test
    public void testFunc02(){

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

       Customer c = new Customer(); // 没有id,没有与session关联,瞬时状态
        c.setCust_name("lisi"); // 没有id,没有与session关联,瞬时状态

        session.save(c); // 有id,与session关联,持久化状态

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close(); //  有id,没有与session关联,游离状态
    }

2.2 hibernate中状态的特点

持久化状态特点:持久化状态对象的任何变化都会自动同步到数据库中

这个时候,不需要调用session.update方法,数据库中的数据依然会更新

@Test
    public void testFunc(){

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

       Customer c = session.get(Customer.class, 1l); // 持久化状态
        c.setCust_name("lisi"); 

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();  //  游离状态
    }

2.3 状态转换图

Java mac idea hibernate的使用02_第1张图片
Snip20180807_30.png

结论:将对象的数据同步到数据库中,对象转化为持久化状态

3. hibernate中的一级缓存

缓存:提高操作数据库的效率

3.1 提高查询效率

Java mac idea hibernate的使用02_第2张图片
Snip20180807_32.png

3.2 减少不必要的修改语句执行

Java mac idea hibernate的使用02_第3张图片
Snip20180807_34.png
@Test
    public void testFunc(){

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

       Customer c1 = new Customer();

        c1.setCust_name("wangwu"); // 托管|游离

        session.update(c1); // c1被放入到session缓存了

        Customer c2 = session.get(Customer.class, 1l); // 从缓存中取出

        // 在提交之前是没有sql语句执行的,
        // 在提交之前会对比session的缓存和快照,这里并没有从数据库中取出对象,所以快照是空的,缓存和快照是不一致的,会执行一次update操作
        
        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();  //  游离状态
    }

4. hibernate中的事务

4.1 事务的特性

a:原子性
c:一致性
i:隔离性
d:持久性

4.2 事务并发问题

  1. 脏读:读到了别人正在修改但是并未提交的数据,导致读取的数据并不是最终确定的数据
  2. 不可重复读:两次连续的读取,数据不一致。可能是有人在第一次读取之后,将数据进行修改并提交了,导致第二次读取的数据和第一次的不同
  3. 虚|幻读:一般是整表操作。在删除整张表的过程中,有人向表中写入数据,在删完之后发现表中竟然还有数据

4.3 事务的隔离级别

读未提交-可能出现的问题 1.2.3
读已提交-可能出现的问题 2.3
可重复读(mysql默认隔离级别)-可能出现的问题 3
串行化-可能出现的问题 无,但是效率太低

4.4 如何在hibernate中指定隔离级别


        4

4.5 在项目中如何管理事务

  1. 业务开始之前打开事务,业务执行之后提交事务,执行过程中出现异常回滚事务
    2.在dao层操作数据库需要用到session,在service层操作数据库也需要用到session,我们需要确保两个session是同一个对象
  2. 在hibernate中确保使用同一个session,只需要调用sessionFactory.getCurrentSession(),底层也是使用的ThreadLocal,绑定线程
        
        thread
public class HibernateUtils {

    private static SessionFactory sessionFactory;

    /// 只能有一个sessionFactory
    static {
        Configuration conf = new Configuration().configure();

        sessionFactory = conf.buildSessionFactory();
    }

    /// 返回不同的session
    public static Session openSession() {
        
        Session session = sessionFactory.openSession();

        return session;
    }

    /// 返回同一个与线程绑定的session
    public static Session getCurrentSession() {

        Session session = sessionFactory.getCurrentSession();

        return session;
    }
}
@Test
    public void testFunc03() {

        Session session1 = HibernateUtils.getCurrentSession();
        Session session2 = HibernateUtils.getCurrentSession();
        System.out.println(session1 == session2); // true
    }

注意:通过getCurrentSession()获得的session对象,当事务提交时,session会自动关闭,不需要手动调用session.close()

4.6 修改01中的项目

将事务的操作从dao层,转到service层

public class CustomerDaoImpl implements CustomerDao {
    @Override
    public void save(Customer customer) {

        Session session = HibernateUtils.getCurrentSession();

        session.save(customer);
    }
}

public class CustomerServiceImpl implements CustomerService {

    private CustomerDao serviceDao = new CustomerDaoImpl();

    @Override
    public void save(Customer customer) {

        Session session = HibernateUtils.getCurrentSession();

        // 打开事务
        Transaction transaction = session.beginTransaction();

        try {
            serviceDao.save(customer);
        } catch (Exception e) {
            e.printStackTrace();
            // 异常,回滚事务
            transaction.rollback();
        }

        // 提交事务
        transaction.commit();
    }
}

5. 批量查询

5.1 HQL查询

  1. 查全部
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 1.书写HQL语句
        String hql = "from Customer ";
        // String hql = "from Customer where cust_id = 1";
        // 2.根据HQL语句创建查询对象
        Query query = session.createQuery(hql);

        // 根据查询对象,获得查询结果
        List list = query.list(); // 返回list结果

        // 接收唯一的查询结果
        // Customer customer = (Customer) query.uniqueResult();

        System.out.println(list);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 设置参数,使用 ? 做占位符 查某一条数据
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 1.书写HQL语句
//        String hql = "from Customer ";
        String hql = "from Customer where cust_id = ?";

        // 2.根据HQL语句创建查询对象
        Query query = session.createQuery(hql);

        query.setParameter(0, 2l);

        // 根据查询对象,获得查询结果
//        List list = query.list(); // 返回list结果

        // 接收唯一的查询结果
         Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 使用hibernate的命名占位符,查询某一条数据
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 1.书写HQL语句
//        String hql = "from Customer ";
        String hql = "from Customer where cust_id = :cust_id";

        // 2.根据HQL语句创建查询对象
        Query query = session.createQuery(hql);

        query.setParameter("cust_id", 2l);

        // 根据查询对象,获得查询结果
//        List list = query.list(); // 返回list结果

        // 接收唯一的查询结果
         Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 设置分页
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 1.书写HQL语句
//        String hql = "from Customer ";
        String hql = "from Customer where cust_id = :cust_id";

        // 2.根据HQL语句创建查询对象
        Query query = session.createQuery(hql);

        // 设置分页,相当于limit ?, ?
        query.setFirstResult(0);
        query.setMaxResults(1);


        // 根据查询对象,获得查询结果
        List list = query.list(); // 返回list结果

        System.out.println(list);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }

5.2 criteria查询

  1. 查询全部
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        Criteria criteria = session.createCriteria(Customer.class);
        
        // 根据查询对象,获得查询结果
        List list = criteria.list(); // 返回list结果

        System.out.println(list);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 条件查询
 @Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 创建 Criteria 对象
        Criteria criteria = session.createCriteria(Customer.class);

        // 添加查询条件
        criteria.add(Restrictions.eq("cust_id", 1l));


        // 根据查询对象,获得查询结果
        Customer customer = (Customer) criteria.uniqueResult(); // 返回list结果

        System.out.println(customer);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 分页查询
@Test
    public void testFunc05() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 创建 Criteria 对象
        Criteria criteria = session.createCriteria(Customer.class);

        // 添加查询条件
        criteria.setFirstResult(0); // 从第0条开始查

        criteria.setMaxResults(1);  // 每页一条

        // 根据查询对象,获得查询结果
        Customer customer = (Customer) criteria.uniqueResult(); // 返回list结果

        System.out.println(customer);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 查询总行数
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        // 创建 Criteria 对象
        Criteria criteria = session.createCriteria(Customer.class);

        // 设置查询的聚合函数,总行数
        criteria.setProjection(Projections.rowCount());

        // 根据查询对象,获得查询结果
        Long rowCount = (Long) criteria.uniqueResult();

        System.out.println(rowCount);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }

5.3 原生sql查询

  1. 查询全部
 @Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        String sql = "select * from t_customer";

        SQLQuery sqlQuery = session.createSQLQuery(sql);
        
        // sqlQuery.list();默认返回的是object[]
        // 指定将结果集封装到哪个对象当中
        sqlQuery.addEntity(Customer.class);

        // 根据查询对象,获得查询结果
        List list = sqlQuery.list();

        System.out.println(list);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 条件查询
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        String sql = "select * from t_customer where cust_id = ?";

        SQLQuery sqlQuery = session.createSQLQuery(sql);

        sqlQuery.setParameter(0, 1l);

        // 指定将结果集封装到哪个对象当中
        sqlQuery.addEntity(Customer.class);

        // 根据查询对象,获得查询结果
        Customer customer = (Customer) sqlQuery.uniqueResult();

        System.out.println(customer);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }
  1. 分页查询
@Test
    public void testFunc() {

        Session session = HibernateUtils.openSession();

        Transaction transaction = session.beginTransaction();

        String sql = "select * from t_customer limit ?, ?";

        SQLQuery sqlQuery = session.createSQLQuery(sql);

        sqlQuery.setParameter(0,0);

        sqlQuery.setParameter(1, 1);

        // 指定将结果集封装到哪个对象当中
        sqlQuery.addEntity(Customer.class);

        // 根据查询对象,获得查询结果
        List list = sqlQuery.list();

        System.out.println(list);

        // 提交事务
        transaction.commit();
        // 释放资源
        session.close();
    }

你可能感兴趣的:(Java mac idea hibernate的使用02)