頁面調試數據: <%@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鏈接指定一下隔 離級別,而後讓數據庫去搞定一切就夠了