1. 程式人生 > >Hibernate下的增刪改查

Hibernate下的增刪改查

set方法 文件 ransac let ice 數據庫表 jdbc ring builder

概述:

關系--對象映射的中間件,屬於開源ORM框架,是我們業務邏輯層中的調用數據庫的中間件

演變:

jdbc---hibernater---mybatis

hibernate和mybatis區別?

1:hiberanter學習的難度要比mybatis要大,復雜度要高
2:hibernate不需要寫sql語句,自動生成,而mybatis需要寫sql語句進行數據操作
3:hibernate支持分頁(API),而mybatis不支持分頁(那是屬於插件)
4:hibernate支持事務處理,而mybaits不支持事務處理(Spring)
5:hibernate支持一級緩存、二級緩存和查詢緩存,而mybaits本身沒有緩存(加載第三方緩存技術)

環境搭建步驟:

1:導包
  <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.3.3.Final</version>
    </dependency>

2:加載配置文件hibernate.cfg.xml(數據庫連接信息)
3:需要增加映射文件(寫的不是sql語句,寫的是實體entity和表table中的字段、類型對應關系)

數據庫工具類:

public class HibernateUitls {

    public static Session getSession() {
        // 獲取數據庫的連接工廠
        // 從工廠中獲取連接session
        Configuration config = new Configuration();
        config.configure("hibernate.cfg.xml");
        SessionFactory sf = config.buildSessionFactory();// 獲取工廠
        Session session = sf.openSession();
        
return session; } }

增刪改查操作

/**
 * 測試hibernate增刪改查
* @author lisi
* @date 2018年8月20日
 */
public class HibernateTest {


    /**
     * 查詢操作---讀操作
     */
    @Test
    public void query(){

        Session session = HibernateUitls.getSession();
        Note note = session.get(Note.class, 63);//根據主鍵查詢
        if (note != null) {
            System.out.println(note.getContext());
        }
    }

    /**
     * 增加---寫操作
     */
    @Test
    public void save(){
        Session session = HibernateUitls.getSession();

        Note note = new Note();
        note.setId(3000);
        note.setContext("java20增加測試數1");
        note.setLikeCount(10);
        note.setUserId(1);
        note.setPublishTime(new Date(System.currentTimeMillis()));

        Transaction ts = session.beginTransaction();//開啟事務處理

        session.save(note);//保存數據
        ts.commit();//提交事物--
        session.close();//關閉連接 
    }


    /**
     * 修改數據
     */
    @Test
    public void update(){

        Session session = HibernateUitls.getSession();

//      Note note = new Note();
        Note note = session.get(Note.class, 3000);
        //note.setId(3000);
        note.setContext("java20增加測試數2");
        Transaction ts = session.beginTransaction();//開啟事務處理
        session.update(note);
        ts.commit();//提交事物--
        session.close();//關閉連接 

    }

    /**
     * 刪除操作
     *  1:先查詢數據是否存在
     *  2:如果存在,則刪除,不存在,則不執行delete
     *  3:hibernate做的安全設置
     */
    @Test
    public void delete(){

        Session session = HibernateUitls.getSession();

        Note note = new Note();
        note.setId(3000);
        Transaction ts = session.beginTransaction();//開啟事務處理
        session.delete(note);
        ts.commit();//提交事物--
        session.close();//關閉連接 
    }

}

Hibernate主鍵管理

策略生成的位置配置:

<id name="id" type="integer" column="id">
    <generator class="identity"></generator>
</id>

1.sequence 序列

主要用於oracle數據庫

2.identity 主鍵自增

主要用於mysql、SqlServer
主鍵自增

3.native

自動識別當前數據庫的類型
如果數據庫為oracle,則默認的ID生成策略為sequence
如果數據庫為mysql等,則默認的ID生成策略為identity

4.increment

代表當前數據庫表的主鍵ID,查詢數據庫ID最大值+1

5.uuid/hilo

采用UUID和hilo的算法,生成一個字符串,當成主鍵ID

6.assigned

是hibernate默認的主鍵生成策略,增加set方法

Hibernate查詢操作

  • SQL:面向結構的查詢 Structured Query Language(結構化)

    select * from note 或者 SELECT * FROM NOTE

  • HQL:面向對象的查詢 hibernater query language(對象化)

    select userid(實體類中的屬性名稱) from Note(實體類名)

HQL和SQL區別?

- HQL是面向對象的查詢,SQL是面向結構化的查詢
- HQL查詢時候對查詢屬性大小寫比較敏感,SQL在查詢的時候對屬性的大小寫依賴於我們的配置
- HQL支持count、sum、avg等,但是HQL不支持類型轉換,比如日期轉換、字符串轉換
- HQL不建議使用left join,而SQL可以無條件的使用
- HQL在做查詢的時候,如果是查詢所有字段信息,則可以省略select *,直接使用from  實體類名
- HQL在查詢的時候,使用的是類名和屬性名,SQL查詢的時候,使用的表名和字段名
- HQL和SQL在使用上,或者處理業務上,HQL只能進行簡單操作,SQL可以進行復雜操作

結構化:

HQL查詢

普通查詢

1:查詢所有的數據

2:根據條件進行查詢

3:分頁條件

4:統計個數

代碼如下:

/**
 * hibernate普通查詢
* @author lisi
* @date 2018年8月21日
 */
public class HQLTest {


    /**
     * 查詢所有的數據
     */
    @Test
    public void query(){
        Session session = HibernateUitls.getSession();
        String hql = "from Note";
        Query query = session.createQuery(hql);
        List<Note> list = query.list();//獲取查詢結果集
        //list.isEmpty()    只會判斷list中的數據是否為空
        //list != null && list.size() > 0  判斷的是對象list是否存在,並且判斷list中是否有數據
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }

    /**
     * 根據條件查詢
     *  select * from note where userId = 3
     */
    @Test
    public void test2(){
        Session session = HibernateUitls.getSession();

        //jpa-style
        //String hql = "from Note where userId=?0";//?代表占位符,占位符下標是從0開始
        String hql = "from Note where userId = :userid";
        Query query = session.createQuery(hql);
//      query.setInteger(0, 3);
//      query.setParameter(0, 3);
        query.setParameter("userid", 3);

        List<Note> list = query.list();//獲取查詢結果集
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }

    /**
     * 分頁查詢
     * 
     *  select * from note limit 0,3;
     */
    @Test
    public void test3(){
        Session session = HibernateUitls.getSession();
        String hql = "from Note";

        Query query = session.createQuery(hql);

        query.setFirstResult(1);//分頁條件limit的第一個參數,下標是從0開始
        query.setMaxResults(3);//分頁條件limit的第二個參數,代表需要查詢的條數

        List<Note> list = query.list();//獲取查詢結果集
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getId());
            }
        }
    }


    /**
     * 統計個數
     *  select count(1) from note
     */
    @Test
    public void test4(){
        Session session = HibernateUitls.getSession();
        String hql = "select count(0) from Note";
        Query query = session.createQuery(hql);
        Long count = (Long) query.uniqueResult();
        System.out.println("統計個數為:" + count);
    }
}

Criteria查詢

多條件查詢、可以根據實體類屬性的字段、排序、分組、分頁、統計個數、and、or等

示例代碼:

/**
 * 多條件查詢
* @author likang
* @date 2018年8月21日
 */
public class CriteriaTest {


    /**
     * select * from note;
     */
    @Test
    public void test1(){
        Session session = HibernateUitls.getSession();
        Criteria criteria = session.createCriteria(Note.class);
        List<Note> list = criteria.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }

    /**
     * select * from note where userId = 3;
     * select * from note where userId = 2 and id = 2005;
     * select * from note where userId = 2 or id = 2005;
     * select * from note where userId = 2 or id = 2005 order by id desc/asc;
     */
    @Test
    public void test2(){
        Session session = HibernateUitls.getSession();
        Criteria criteria = session.createCriteria(Note.class);
//      criteria.add(Restrictions.eq("userId", 2));
//      criteria.add(Restrictions.eq("id", 2005));
        criteria.add(Restrictions.or(Restrictions.eq("userId", 2), Restrictions.eq("id", 2005)));
//      criteria.addOrder(Order.desc("id"));
        criteria.addOrder(Order.asc("id"));

        List<Note> list = criteria.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }

    /**
     * hibernate5新特性寫法:
     *  select * from note where userId = 3;
     */
    @Test
    public void test3(){
        Session session = HibernateUitls.getSession();
        CriteriaBuilder crb = session.getCriteriaBuilder();
        CriteriaQuery<Note> criteria = crb.createQuery(Note.class);
        Root<Note> root = criteria.from(Note.class);
        criteria.where(crb.equal(root.get("userId"), 1));
        Query<Note> query = session.createQuery(criteria);
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }
}

NativeSQL查詢

原生查詢、支持sql語句的查詢

示例代碼:

/**
 * 原生sql語句查詢
* @author lisi
* @date 2018年8月21日
 */
public class NativeSQLTest {


    @Test
    public void test1(){
        Session session = HibernateUitls.getSession();
        String sql = "select * from note";
//      SQLQuery query = session.createSQLQuery(sql);
//      List<Object[]> list = query.list();
//      if (list != null && list.size() > 0) {
//          for (Object[] obj : list) {
//              System.out.println(obj[1]);
//          }
//      }

        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Note.class);//在進行遍歷之前,提前進行數據映射轉換
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }


    /**
     * hibernate5新特性寫法:
     */
    @Test
    public void test2(){
        Session session = HibernateUitls.getSession();
        String sql = "select * from note where userId = 3";
        NativeQuery query = session.createNativeQuery(sql);

        query.addEntity(Note.class);//在進行遍歷之前,提前進行數據映射轉換
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容為:" + list.get(i).getContext());
            }
        }
    }

}

Hibernate註解應用

類上面註解:

@Entity
@Table(name="note")

方法屬性註解:

@Id
@Column(name="數據庫中字段主鍵")
@GeneratedValue(generator="identity")
private int id;//主鍵

其它字段:

    @Column(name="數據庫中字段名稱")

修改hibernate.cfg.xml配置文件:

<mapping class="com.xdl.entity.Note"/>

Hibernate特性

延遲加載

hibernate中的API,有一些是具有延遲加載的特性,對象在調用的時候,才會進行數據加載(什麽時候調用,什麽時候加載)

get、list方法,不具有延遲加載特性
load、find方法,具有延遲加載特性

問題:

    ...... no session

問題請求:

接口請求--->web.xml--->action--->service--->dao(session關閉)--->view

解決:

接口請求--->web.xml--->action--->service--->dao(session不關閉)--->view--->關閉session(事務spring)

緩存(性能優化)

緩存:對象在第一次使用的時候,是進行數據加載(需要查詢數據庫),下一次查詢同樣條件的數據,則直接從緩存中獲取,而並發查詢數據庫(速度快、減輕數據庫服務器壓力)
  • 一級緩存

    自動開啟,不需要做任何的配置和修改 特點: session獨享

  • 二級緩存

    特定: session共享

  • 查詢緩存

持久化(session)

  • 臨時狀態

    可以被JVM進行垃圾回收

  • 持久化狀態

    不能更直接被JVM回收,可以先變成其它兩種狀態之後,才會進行垃圾回收

  • 遊離狀態

    可以被JVM進行垃圾回收

技術分享圖片

技術分享圖片

Spring+Hibernate整合

整合結構:

技術分享圖片

整合步驟:

1:導包
    hibernate-core
2:導入spring包

3:加載spring和hibernate配置文件

4:在spring的配置文件中,增加數據庫的連接信息和事務管理

5:將原來的工程進行改造---jdbc實現類註釋,增加一個hibernate實現類

6:實現接口方法

7:部署、啟動、訪問

核心代碼:

applicationContext.xml:
<!-- 加載hibernateTemplate -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <!-- 加載sessionFacotory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="c3p0"></property>
        <property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
    </bean>

    <!-- 處理事務 -->
    <bean id="txManger" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <!-- 事務支持註解驅動 -->
    <!-- proxy-target-class:屬性默認為false,則代表是使用jdk本身的代理(靜態代理)
        true:則代表使用的是cglib代理(動態代理模式)
     -->
    <tx:annotation-driven transaction-manager="txManger" proxy-target-class="true"/>


HibernateServiceImpl.java:
 @Repository
    public class HibernateServiceImpl implements INoteService{

        @Resource
        private HibernateTemplate hibernateTemplate;

        @Override
        public List<Note> queryNoteList(int userid) {
            DetachedCriteria dCriteria = DetachedCriteria.forClass(Note.class);
            dCriteria.add(Restrictions.eq("userId", userid));
            List<Note> list = (List<Note>) hibernateTemplate.findByCriteria(dCriteria);
            String hql = "from Note where userId=:userId";
            List<Note> list1 = (List<Note>) hibernateTemplate.findByNamedParam(hql, "userId", userid);
            return list1;
        }

        @Override
        public int deleteNotesById(int id) {
            Note note = hibernateTemplate.get(Note.class, id);
            if (note != null) {
                hibernateTemplate.delete(note);
                return 1;
            }
            return 0;
        }
    }

如果有刪除操作,需要在刪除的action的類頭上加上標註,將只讀模式關閉
@Transactional(readOnly=false)//將只讀模式進行關閉
DeleteAction.java:

Hibernate下的增刪改查