筆記之_java整理hibernate

頁面調試數據:
<%@taglib uri="/struts-tags" prefix="s" %>
<s:debug></s:debug>
Js清除緩存
使用hibernate延遲加載時,而且數據庫有關聯關係,轉換成json對象時不能直接轉換,要用new JSONObject(),而後put()方法存值
國外框架項目地址:http://websystique.com/springmvc/spring-mvc-4-angularjs-example/
Angularjs文本輸入框用ng-moduel,其餘的用{{ }}
放行用.*?
Angularjs插件地址http://www.cnblogs.com/pilixiami/p/5634405.html
UI班的教程:http://pan.baidu.com/share/link?shareid=4146906997&uk=866705889
非嚴格讀寫是併發的概念
Spring不支持多線程
Flush()強制要求緩存與數據庫一致
Eache錶鏈接,lazy子查詢
ORM:
    編寫程序時,以面向對象的方式處理數據
    保存數據時是以關係型數據庫的方式存儲的
Hibernate的數據持久化:
    New實例化對象時默認是瞬時的
    Jdbc鏈接數據庫時,持久化數據
    將數據存入硬盤
單向關聯關係:
    一個類單方向包含另外一個類爲屬性,模擬數據庫外鍵
mysql數據庫附加:
String  driver=com.mysql.jdbc.Driver
String url=jdbc:mysql://localhost:3306/demo
hibernate注入:
    實體類
(1)這個表示一個實體類,Table表示對應數據庫中的表名。
@Entity
@Table(name="t_emp")
(2)這個表示主鍵自動增加
mysql數據庫
@Id
@GeneratedValue
oracle數據庫
@Id
@SequenceGenerator(name = "FLINKSEQ", sequenceName = "flink_seq", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "FLINKSEQ")
(3)這個表示關聯對象以及關聯的字段名字
@ManyToOne
@JoinColumn(name="dept_id")

@OneToMany(mappedBy="flinkType") //主表實體類映射關係
(4)和數據庫中字段不同的,要經過這個屬性寫清楚。
@Column(name="emai")
(5)表示時間字段
@Temporal(TemporalType.TIMESTAMP)
和@Temporal(TemporalType.DATE)
    Dao.impl包中:
        @Repository實體類數據訪問層實現,放在類上
    Service.impl包中:
        @Service實體類業務邏輯層實現,放在類上
@Resource(name="flinkTypeDaoImpl")屬性注入值放在setter方法上
    Controller包中:
@Controller 是servlet標誌,放在類上
@Scope(value="prototype") 每次實例化,放在類上
@Resource(name="flinkTypeServiceImpl")賦值,屬性的setter方法上
    測試類:放測試類上
@ContextConfiguration(locations="classpath:applicationContext.xml")
@RunWith(value=SpringJUnit4ClassRunner.class)

struts傳參:
getter方法
ActionContext.getContext().getContextMap().put("arrLinks", arrLinks);
struts頁面取值:
#r.id
id
@manyTomany必須有第三個表爲中間表,命名爲中間表的表名爲:表名_表名2,命名不規範要@ManyToMany(mappedBy="表名")
在hibernate中分頁參數與mysql一致,排除幾筆取幾筆
Hibernate不用stringMVC而是用ORM框架
Mybaties鏈接數據庫用的數據庫鏈接池是dbcp,而hibernate用c3p0
Hibernate鏈接數據庫還要麪包切的jar包

Hibernate實體類的生命週期:
瞬時狀態:剛用new語句建立,尚未被持久化,且不處於session的緩存中
持久狀態:已被持久化,且加入到session緩存中,執行了update()或save()方法時
遊離狀態:已經被持久化,可是再也不處於session緩存中

jdbc與hibernate區別 ?
JDBC與hibernate在性能上相比,JDBC靈活性有優點。
而Hibernate在易學性,易用性上有些優點。
當用到不少複雜的多表聯查和複雜的數據庫操做時,JDBC有優點。
相同點:
二者都是Java的數據庫操做。
二者對於數據庫進行直接操做的對象都不是線程安全的,都須要及時關閉。
二者均可以對數據庫的更新操做進行顯式的事務處理。
不一樣點:
使用的SQL語言不一樣:
JDBC使用的是基於關係型數據庫的標準SQL語言,
Hibernate使用的是HQL(Hibernate query language)語言
操做的對象不一樣:
JDBC操做的是數據,將數據經過SQL語句直接傳送到數據庫中執行,
Hibernate操做的是持久化對象,由底層持久化對象的數據更新到數據庫中。
數據狀態不一樣:
JDBC操做的數據是「瞬時」的,變量的值沒法與數據庫中的值保持一致,
而Hibernate操做的數據是可持久的,即持久化對象的數據屬性的值是能夠跟數據庫中的值保持一致的。
has  a     和    is a的區別?
     has a     包含關係   (對象之間有關聯關係)
     is a      繼承       (泛化關係)


JDBC與框架的區別:
Jdbc:  
1)、要求sql比較精通
2)、對jdbc操做循環取值要細心,重複工做量很大
3)、對jdbc操做insert,update拼接字符串,要求細心
Hibernate:   不懂sql也沒有太大的關係,只要按hibernate框架語法來操做就好了




2、要使用hiberante步驟
  1)、配置核心的配置文件 
         Mybatis-->鏈接數據庫,用戶名,密碼.....,調試sql
         Hibernate-->也是同樣的(名稱 hibernate.cfg.xml)
  2)、java實體類與數據庫表創建映射關係
      可能還會有   一對多,  多對一   多對多   一對一
        Mybaits以接口爲核心
CityMapper.java -->CityMapper.xml(本身寫insert,update,delete,select)
       Hiberante:以實體類爲核心,insert,update,delete,select不會本身作
  3)、編寫工具類
       Mybatis中取 SqlSessionFactory  --> session  --> 操做 -->(提交事務 可選)
       Hibernate中取  SessionFactory   -->session -->開啓事務 -->操做-->提交事務
3、實體類與數據庫表映射在hibernate中有2種寫法
公司實際開發中,確定是使用註解
學習中使用xml
4、hibernate日期格式
@Temporal(TemporalType.TIMESTAMP)  yyyy-MM-dd hh:mm:ss
@Temporal(TemporalType.DATE)        yyyy-MM-dd
@Temporal(TemporalType.TIME)        hh:mm:ss
    public Date getDtime() {
        return dtime;
    }
5、外鍵
   Hibernate:  
        1:1    @OneToOne
        1:n    @OneToMany
        N:1    @ManyToOne
        N:M    @ManyToMany
六、N:1 配置屬性
@ManyToOne(fetch=FetchType.LAZY )
Fetch 檢索加載的方式   EAGER  當即查詢
                        LAZY   延遲加載(保證 session未關閉)
@JoinColumn(name="typeId")  外鍵列
7、配置核心hibernate.cfg.xml
<hibernate-configuration>
    <session-factory>
          1)、聲明 你用的是哪一種數據庫 (斷言  方言  hibernate.dialect)
          2)、驅動包      hibernate.connection.driver_class
       3)、用戶名   hibernate.connection.username
       4)、密碼     hibernate.connection.password
       5)、url      hibernate.connection.url
         6)、顯示sql     hibernate.show_sql=true/false
       7)、是否自動維護表結構 
           hibernate.hbm2ddl.auto     update
1)、none     不須要維護
2)、create-only   若是實體類有對象,數據庫沒有,就會建立
3)、drop  每次關閉項目就會刪除全部的表
4)、create    每次啓動都要從新建立表
5)、create-drop每次啓動從新建立表,關閉時候刪除全部表
6)、update  若是實體類與表結構不一致,就自動更新 
7)、取得session的方式
         hibernate.current_session_context_class  thread
 8)、在沒有spring框架的狀況下,必須把你定義好的帶有註解的實體類,交給核心配置文件
        <mapping  class=」完整類路徑」 />
         之後還有數據庫鏈接池配置
        </session-factory>
</hibernate-configuration>
8.sessionFactory.openSession()和sessionFactory.getCurrentSession()區別(面試題)
openSession()  打開之後,必須手動的關閉close();
getCurrentSession()打開之後,不須要關閉,交給當前應用自動管理,可是必須在hibernate.cfg.xml中配置
<property name="hibernate.current_session_context_class">thread</property>
9、使用hibernate增,刪,改操做   語法
//一、建立Session
         Session session=HibernateUtil.getCurrentSession();
        //二、開啓事務
         Transaction trans=session.beginTransaction();
        try {
              操做
            //提交
            trans.commit();
        } catch (Exception e) {
            trans.rollback();
            //回滾
            e.printStackTrace();
        }        
不在事務執行範圍內的操做沒有效果










hibernate的get()和load()方法的區別:
1. 對於get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,而後在二級緩存中查找,尚未就查詢數據庫,數據庫中沒有就返回null。
2.  load方法加載實體對象的時候,根據映射文件上類級別的lazy屬性的配置(默認爲true),分狀況討論:
(1)若爲true,則首先在Session緩存中查找,看看該id對應的對象是否存在,不存在則使用延遲加載,返回實體的代理類對象(該代理類爲實體類的子類,由CGLIB動態生成)。等到具體使用該對象(除獲取OID之外)的時候,再查詢二級緩存和數據庫,若仍沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
(2)若爲false,就跟get方法查找順序同樣,只是最終若沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
這裏get和load有兩個重要區別:
若是未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException。
load方法可返回沒有加載實體數據的代理類實例,而get方法永遠返回有實體數據的對象。
配置對外關係時:
@ManyToOne(fetch=FetchType.LAZY)子查詢
@ManyToOne(fetch=FetchType.EAGER)錶鏈接
雙向關聯關係:

    private List<Flink> arrFlinks=new ArrayList<Flink>(0);
    @OneToMany(mappedBy="linkType")  
    public List<Flink> getArrFlinks() {
        return arrFlinks;
    }

    private FlinkType linkType; // 分類(惟一的)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "typeId")
    public FlinkType getLinkType() {
        return linkType;
    }












面試題權限操做 (下午看)
多用戶多權限系統 
 用戶名: Users (userId(PK)  , userName)
 角色表: Role( roleId(PK),roleName);
 功能(菜單)表Func(funcId(PK),  funcName, funcUrl,   parentId(FK-->funcId),  isShow);
 角色用戶表: role_user(id,  userId(FK), foleId(FK))
 角色功能表: role_func(id,  roleId(FK),  funcId(FK))
 
多用戶單權限系統 
 用戶名:  Users (userId(PK)  , userName, roleId(FK))
 角色表: Role( roleId(PK),roleName);
 功能(菜單)表  Func(funcId(PK),  funcName, funcUrl,   parentId(FK-->funcId),  isShow);
 角色功能表: role_func(id,  roleId(FK),  funcId(FK))

hibernate的查詢方式:
    hql查詢:
Session session=sessionFactory.getCurrentSession();
Query query=session.createQuery(hql);
    自定義sql查詢:
Session session=sessionFactory.getCurrentSession();
SQLQuery sqlQuery=session.createSQLQuery(sql);
    標準查詢:
Session session=sessionFactory.getCurrentSession();
Criteria criteria=detachedCriteria.getExecutableCriteria(session);
分頁查詢:
.setFirstResult(firstResult);  //起始數據
.setMaxResults(maxResults);  //取得數據條數
hibernate在批量操做的時候,如何優化性能?
   批量新增,批量修改,批量刪除
   一次性新增、刪除、刪除100個元素?
      千萬不要一次性新增到最後現去 提交,效率很低
   每20個更新一次    session.flush()   session.clear()
  for(int i=0;i<100000;i++){
        Monkey monkey=new Monkey(....);
        session.save(monkey);
        if(i%20==0){    //單批次操做的最大數量
            session.flush();
            session.clear();
        }
    }
   爲什麼這裏寫20不是其它的數字,能夠去hibernate.batch_size=20


何時要用update,何時要用merge?
update():若是你肯定在當前session的會話裏不存在一個與要進行update操做有相同標識符(主鍵)的持久化對象,那麼調用update()。
修改頁面->根據id查詢(session緩存中:id=2)-->頁面(隱藏域放主鍵的=2)-->
editSave( new 實體類(  id=2))   這時候就會報異常了 (可使用merge來解決,還可使用,根據id查詢時候,session.evict(obj) )
merge():若是你在任什麼時候候修改了數據都想把數據保存到數據庫中,那麼就調用merge()。


查詢條件:類型 下拉列表 
String hql=「from  Flink f  where   f.linkType.id=?」   對象導航查詢
Sql: select *  from  Flnk f inner join  FlinkType t on f.typeId=t.id
     Where  t.id=?

String hql=」 from Flink f  left out join fetch
 f.linkType  t
Where  t.id=?」;
幫你生成 inner join



update和saveOrUpdate的區別? 
  update()修改根據主鍵數據庫中的數據 
 saveOrUpdate()若是該對象未持久化(沒有新增過)執行save方法,若是已經持久化了,那就執行update修改操做。

1、hibernate的三種狀態之間如何轉換  
  瞬時狀態、持久狀態、遊離狀態
  
當調用 save(),update()  對象變爲持久化狀態
  當實例化對象,就是瞬時狀態
  當調用delete()遊離狀態,脫離了session都叫遊離狀態
  
3、session.clear(),session.evict(Object)
   clear()  移出全部在session(一級緩存,只能在內存存在)管理的緩存
   evict()  從session緩存中移出某個指定的對象

4、Hibernate工做原理及爲何要用? 
原理: 
1.讀取並解析配置文件 
2.讀取並解析映射信息,建立SessionFactory 
3.打開Sesssion 
4.建立事務Transation 
5.持久化操做 
6.提交事務 
7.關閉Session 
8.關閉SesstionFactory (二級緩存,須要使用第三方框架)
爲何要用: 
.對JDBC訪問數據庫的代碼作了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。 
.Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工做 
.hibernate使用Java反射機制。 
.hibernate的性能很是好,由於它是個輕量級框架。映射的靈活性很出色。它支持各類關係數據庫,從一對一到多對多的各類複雜關係。對緩存支持的



4.Hibernate是如何延遲加載? 
. Hibernate2延遲加載實現:a)實體對象   b)集合(Collection) 
. Hibernate3\4\5 提供了屬性的延遲加載功能 
當Hibernate在查詢數據的時候,數據並無存在與內存中,當程序真正對數據的操做時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而
提升了服務器的性能。
5.Hibernate中怎樣實現類之間的關係?(如:一對多、多對多的關係) 
類與類之間的關係主要體如今表與表之間的關係進行操做,它們都市對對象進行操做,咱們程序中把全部的表與類都映射在一塊兒,它們經過配置文件中的
many-to-one、one-to-many、many-to-many、
6.說下Hibernate的緩存機制 
. 內部緩存存在Hibernate中又叫一級緩存(session),屬於應用事物級緩存 
. 二級緩存:(SessionFactory) 
a) 應用及緩存 
b) 分佈式緩存 
條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非關鍵數據 
c) 第三方緩存的實現 (EhCache)
5. Hibernate的查詢方式 
Session.get()  當即加載
Session.load()  延遲加載
Sql、  
Hql,   
Criteria,   
object comptosition  (對象導航)
6. 如何優化Hibernate? 
.使用雙向一對多關聯,不使用單向一對多 
.靈活使用單向一對多關聯 
.不用一對一,用多對一取代 
.配置對象緩存,不使用集合緩存  
.表字段要少,表關聯不要怕多,有二級緩存撐腰
7. get和load區別;
1)get若是沒有找到會返回null, load若是沒有找到會拋出異常。
2)get會先查一級緩存, 再查二級緩存,而後查數據庫;
load會先查一級緩存,若是沒有找到,就建立代理對象, 等須要的時候去查詢二級緩存和數據庫。

8. N+1問題。
Hibernate中常會用到
解決方法一個是延遲加載, 即lazy=true;
   Select * from Flink  -->FlinkType(延遲的)
  當調用對象.getFlinkType() 纔去查詢   
再發送一個select * from FlinkType where id=?
一個是預先抓取 FetchType.EAGER, 即;  left join
11 persist()和save()的區別 (瞭解)
persist不保證當即執行,可能要等到flush;persist不更新緩存;
12 cascade,用來指示在主對象和它包含的集合對象的級聯操做行爲,即對住對象的更新怎麼影響到子對象;
save-update:   級聯保存(load之後若是子對象發生了更新,也會級聯更新). 但它不會級聯刪除
delete:              級聯刪除, 但不具有級聯保存和更新
all-delete-orphan: 在解除父子關係時,自動刪除不屬於父對象的子對象, 也支持級聯刪除和級聯保存更新.
all:                    級聯刪除, 級聯更新,但解除父子關係時不會自動刪除子對象. 
delete-orphan:刪除全部和當前對象解除關聯關係的對象
13 session.commit 和flush區別,
 commit會先調用flush 而後再執行clear(),而後提交事物;
 flush() 強制地要求內存對象 與 數據庫中的數據保持一致(同步)
 flush 執行session,但不必定提交事物(由於事物可能被委託給外圍的aop代理來作);
14 session清理的順序: insert -> update -> delete -> 對集合進行delete -〉對集合的insert;
15 檢索策略: 當即檢索,lazy=false;延遲加載:lazy=true;預先抓取: fetch=「join」;
17、數據庫事務
  1)、四個特性
        原子性、一致性,隔離性, 持久性
  2)、事務隔離級別
           Serializable:     串行化。隔離級別最高   4
           Repeatable Read:可重複讀            3(mysql)
           Read Committed:已提交數據讀        2 (oracle)
           Read Uncommitted:未提交數據讀。隔離級別最差   1
     
   隔離級別越高的,數據精準性高,速度慢。
   隔離級別越低的,查詢速度快,可是數據精準性低.
      

1.    髒讀: 對於兩個事物 T1, T2, T1 讀取了已經被 T2 更新但尚未被提交的字段. 以後, 若 T2 回滾, T1讀取的內容就是臨時且無效的.  
2.    不可重複讀: 對於兩個事物 T1, T2, T1 讀取了一個字段, 而後 T2 更新了該字段. 以後, T1再次讀取同一個字段, 值就不一樣了.  
3.    幻讀: 對於兩個事物 T1, T2, T1 從一個表中讀取了一個字段, 而後 T2 在該表中插入了一些新的行. 以後, 若是 T1 再次讀取同一個表, 就會多出幾行.  
Read uncommitted 讀未提交
公司發工資了,領導把5000元打到singo的帳號上,可是該事務並未提交,而singo正好去查看帳戶,發現工資已經到帳,是5000元整,很是高興。但是不幸的是,領導發現發給singo的工資金額不對,是2000元,因而迅速回滾了事務,修改金額後,將事務提交,最後singo實際的工資只有2000元,singo空歡喜一場。

 
出現上述狀況,即咱們所說的髒讀,兩個併發的事務,「事務A:領導給singo發工資」、「事務B:singo查詢工資帳戶」,事務B讀取了事務A還沒有提交的數據。
當隔離級別設置爲Read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。
Read committed 讀提交
singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉帳,把singo工資卡的2000元轉到另外一帳戶,並在singo以前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,爲什麼......
出現上述狀況,即咱們所說的不可重複讀,兩個併發的事務,「事務A:singo消費」、「事務B:singo的老婆網上轉帳」,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
當隔離級別設置爲Read committed時,避免了髒讀,可是可能會形成不可重複讀。
大多數數據庫的默認級別就是Read committed,好比Sql Server , Oracle。如何解決不可重複讀這一問題,請看下一個隔離級別。
Repeatable read 重複讀
當隔離級別設置爲Repeatable read時,能夠避免不可重複讀。當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉帳。
雖然Repeatable read避免了不可重複讀,但還有可能出現幻讀。
singo的老婆工做在銀行部門,她時常經過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)爲80元,而singo此時正好在外面胡吃海塞後在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額爲1080元,singo的老婆很詫異,覺得出現了幻覺,幻讀就這樣產生了。
3)鎖機制
     Mysql,sqlserver悲觀鎖:    當某個用戶在操做的時候,其它用戶不容許進行更新數據
                鎖整個表,鎖行
               Select    * from   表                 for update;(oracle樂觀鎖)
              Select    * from   表  where id=5     for update;
              直接上一個用戶 提交或者回滾記錄才行 
     樂觀鎖:
           你們均可進行操做,可是會以某一個列(timestamp 系統自動維護)
           編號    值      version
         1         test    2017-1-1 20:10:2.101
     Update  表 set 值=‘a’   where 編號=1 and veresion=’ 2017-1-1 20:10:2.101’
    Commit;


16、什麼是Hibernate的併發機制?怎麼去處理併發問題? 
 Hibernate併發機制:
 a、Hibernate的Session對象是非線程安全的,對於單個請求,單個會話,單個的工做單元(即單個事務,單個線程),它一般只使用一次,  而後就丟棄。 
      若是一個Session 實例容許共享的話,那些支持併發運行的,例如Http request,session beans將會致使出現資源爭用。 
     若是在Http Session中有hibernate的Session的話,就可能會出現同步訪問Http Session。只要用戶足夠快的點擊瀏覽器的「刷新」,  就會致使兩個併發運行的線程使用同一個Session。  
b、多個事務併發訪問同一塊資源,可能會引起第一類丟失更新,髒讀,幻讀,不可重複讀,第二類丟失更新一系列的問題。
解決方案:設置事務隔離級別。  
    Serializable:串行化。隔離級別最高  
    Repeatable Read:可重複讀  
    Read Committed:已提交數據讀  
    Read Uncommitted:未提交數據讀。隔離級別最差  
設置鎖:樂觀鎖和悲觀鎖。  
樂觀鎖:使用版本號或時間戳來檢測更新丟失,在的映射中設置 optimistic-lock=」all」能夠在沒有版本或者時間戳屬性映射的狀況下實現 版本檢查,此時Hibernate將比較一行記錄的每一個字段的狀態 
行級悲觀鎖:Hibernate老是使用數據庫的鎖定機制,從不在內存中鎖定對象!只要爲JDBC鏈接指定一下隔 離級別,而後讓數據庫去搞定一切就夠了 
相關文章
相關標籤/搜索