風人園

          弱水三千,只取一瓢,便能解渴;佛法無邊,奉行一法,便能得益。
          隨筆 - 99, 文章 - 181, 評論 - 56, 引用 - 0
          數據加載中……

          2011年11月9日

          Spring boot+Spring Security 4配置整合實例

          http://blog.csdn.net/code__code/article/details/53885510

          1. 使用Spring Security管理用戶身份認證、登錄退出

          2. 用戶密碼加密及驗證

          3. 采用數據庫的方式實現Spring Securityremember-me功能

          4. 獲取登錄用戶信息。

          5.使用Spring Security管理url和權限

          posted @ 2018-03-19 21:02 風人園 閱讀(318) | 評論 (0)編輯 收藏

          spring security 參數配置

               摘要:         // 自定義登錄頁面          http.csrf().disable().formLogin().loginPage("/login")  //指定登錄頁的路徑&n...  閱讀全文

          posted @ 2018-03-19 20:33 風人園 閱讀(434) | 評論 (0)編輯 收藏

          spring quartz 串行配置

          <bean id="jobDetail7"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

                             <propertyname="targetObject" ref="billingBillTask"></property>

                             <propertyname="targetMethod" value="executeInternal" />

                             <propertyname="concurrent" value="false" />

                   </bean>

                   <beanid="billingBillTask"class="com.dangdang.tms.job.schedule.bms.BillingBillTask"/>

                   <beanid="cronTriggerBean7" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

                             <propertyname="jobDetail" ref="jobDetail7"></property>

                             <propertyname="cronExpression" value="0/5 * * * * ?"></property>

                   </bean>

          參考 http://blog.csdn.net/lkforce/article/details/51841890

          posted @ 2018-03-12 19:58 風人園 閱讀(388) | 評論 (0)編輯 收藏

          spring 3.0 async 異步方法 設置

          為了解決一些比較費時且不是很緊要的任務,將此任務轉為異步任務處理,提高前端操作體驗。 spring 中 自帶注解 @Async. 配置如下 applicationContext.xml 中 增加 task的引用 如上配置之后,只需要在 需要進行異步調用的方法前面增加 注解就可以了。 @Async public void updateOrderBillItemPQty(String deptId, String orderNo, Integer orderItemSid, Double pQty) { 注:需要注意,同一個對象里面方法調用,不會作為異步方法執行。

          posted @ 2017-05-24 14:27 風人園 閱讀(263) | 評論 (0)編輯 收藏

          android ResourceNotFoundException


          在對 TextView 或者 EditText 進行賦值時,調用setText()方法,一定要注意,使用String類型,不要使用int 或者long,否則 會出現找不到資源的異常。系統自動會將int作為一個資源ID,然后去R 里面找,結果找不到。

          posted @ 2016-12-21 20:48 風人園 閱讀(137) | 評論 (0)編輯 收藏

          android 系統提示對話框(AlertDialog)的使用(zt)

               摘要: http://blog.csdn.net/meng425841867/article/details/8523730 在按鍵單擊事件中添加創建對話框并設置相關屬性。        [java] view plain copy dialogButton=(Button)findViewBy...  閱讀全文

          posted @ 2016-12-02 12:54 風人園 閱讀(476) | 評論 (0)編輯 收藏

          Android 自定義ListView adapter(zt)

               摘要: http://daoshud1.iteye.com/blog/1874241 本文講實現一個自定義列表的Android程序,程序將實現一個使用自定義的適配器(Adapter)綁定 數據,通過contextView.setTag綁定數據有按鈕的ListView。 系統顯示列表(ListView)時,首先會實例化一個適配器,本文將實例化一個自定義的適配器。實現 自定義適...  閱讀全文

          posted @ 2016-12-01 13:13 風人園 閱讀(168) | 評論 (0)編輯 收藏

          Android之SimpleAdapter簡單實例和SimpleAdapter參數說明(zt)

               摘要: http://blog.csdn.net/x605940745/article/details/11981049 SimpleAdapter的參數說明 第一個參數 表示訪問整個android應用程序接口,基本上所有的組件都需要 第二個參數表示生成一個Map(String ,Object)列表選項 第三個參數表示界面布局的id  表示該文件作為列表項的組件&...  閱讀全文

          posted @ 2016-12-01 13:12 風人園 閱讀(184) | 評論 (0)編輯 收藏

          android開發教程之listview使用方法

          首先是布局文件,這里需要兩個布局文件,一個是放置列表控件的Activity對應的布局文件 main.xml,另一個是ListView中每一行信息顯示所對應的布局 list_item.xml 這一步需要注意的問題是ListView 控件的id要使用Android系統內置的 android:id="@android:id/list"

          main.xml
          <?xml version="1.0" encoding="utf-8"?>
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width
          ="match_parent"
              android:layout_height
          ="match_parent"
              android:orientation
          ="vertical" >
                  
          <ListView 
                  
          android:id="@android:id/list"
                  android:layout_width
          ="match_parent"
                  android:layout_height
          ="match_parent"
                  android:padding
          ="20dip"/>
          </LinearLayout>

          list_item.xml
          <?xml version="1.0" encoding="utf-8"?>
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width
          ="match_parent"
          android:layout_height
          ="match_parent"
          android:orientation
          ="horizontal" >

          <TextView
          android:id="@+id/user_name"
          android:layout_width
          ="match_parent"
          android:layout_height
          ="match_parent"
          android:layout_weight
          ="1"/>
          <TextView
          android:id="@+id/user_id"
          android:layout_width
          ="match_parent"
          android:layout_height
          ="match_parent"
          android:layout_weight
          ="1"/>
          </LinearLayout>


          然后就設置MainActivity中的代碼了:基本思想就是先將數據添加到ArrayList中,然后在設置SimpleAdapter適配器完成設置,入下:

          package com.example.android_newlistview;

          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.Map;

          import android.os.Bundle;
          import android.app.Activity;
          import android.app.ListActivity;
          import android.view.Menu;
          import android.widget.SimpleAdapter;

          public class MainActivity extends ListActivity {


          String[] from
          ={"name","id"}; //這里是ListView顯示內容每一列的列名
          int[] to={R.id.user_name,R.id.user_id}; //這里是ListView顯示每一列對應的list_item中控件的id

          String[] userName
          ={"zhangsan","lisi","wangwu","zhaoliu"}; //這里第一列所要顯示的人名
          String[] userId={"1001","1002","1003","1004"}; //這里是人名對應的ID

          ArrayList
          <HashMap<String,String>> list=null;
          HashMap
          <String,String> map=null;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          // TODO Auto-generated method stub
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          //為MainActivity設置主布局
          //創建ArrayList對象;
          list=new ArrayList<HashMap<String,String>>();
          //將數據存放進ArrayList對象中,數據安排的結構是,ListView的一行數據對應一個HashMap對象,
          //HashMap對象,以列名作為鍵,以該列的值作為Value,將各列信息添加進map中,然后再把每一列對應
          //的map對象添加到ArrayList中

          for(int i=0; i<4; i++){
          map
          =new HashMap<String,String>(); //為避免產生空指針異常,有幾列就創建幾個map對象
          map.put("id", userId[i]);
          map.put(
          "name", userName[i]);
          list.add(map);
          }


          //創建一個SimpleAdapter對象
          SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.list_item,from,to);
          //調用ListActivity的setListAdapter方法,為ListView設置適配器
          setListAdapter(adapter);
          }

          }


          另外對點擊某一行作出響應的方法是覆寫onListItemClick方法,根據返回的position(從0開始):
          @Override
          protected void onListItemClick(ListView l, View v, int position, long id) {
          // TODO Auto-generated method stub
          super.onListItemClick(l, v, position, id);
          }


          posted @ 2016-12-01 13:08 風人園 閱讀(157) | 評論 (0)編輯 收藏

          android json 數據解析



          單數據{'singer':{'id':01,'name':'tom','gender':'男'}} 
          多個數據{"singers":[ 
                  {'id':02,'name':'tom','gender':'男'}, 
                   {'id':03,'name':'jerry,'gender':'男'}, 
          {'id':04,'name':'jim,'gender':'男'}, 
          {'id':05,'name':'lily,'gender':'女'}]}          
          // 普通Json數據解析 
              private void parseJson(String strResult) 
                  
          try 
                      JSONObject jsonObj 
          = new JSONObject(strResult).getJSONObject("singer"); 
                      
          int id = jsonObj.getInt("id"); 
                      String name 
          = jsonObj.getString("name"); 
                      String gender 
          = jsonObj.getString("gender"); 
                      tvJson.setText(
          "ID號"+id + ", 姓名:" + name + ",性別:" + gender); 
                  }
           catch (JSONException e) 
                      System.out.println(
          "Json parse error"); 
                      e.printStackTrace(); 
                  }
           
              }
           
              
          //解析多個數據的Json
             private void parseJsonMulti(String strResult) 
                 
          try 
                      JSONArray jsonObjs 
          = new JSONObject(strResult).getJSONArray("singers"); 
                      String s 
          = ""
                      
          for(int i = 0; i < jsonObjs.length() ; i++)
                          JSONObject jsonObj 
          = ((JSONObject)jsonObjs.opt(i)).getJSONObject("singer"); 
                          
          int id = jsonObj.getInt("id"); 
                          String name 
          = jsonObj.getString("name"); 
                          String gender 
          = jsonObj.getString("gender"); 
                          s 
          +=  "ID號"+id + ", 姓名:" + name + ",性別:" + gender+ "\n" ; 
                      }
           
                      tvJson.setText(s); 
                  }
           catch (JSONException e) 
                      System.out.println(
          "Jsons parse error !"); 
                      e.printStackTrace(); 
                  }
           
              }
           

          posted @ 2016-11-29 15:09 風人園 閱讀(163) | 評論 (0)編輯 收藏

          button onClick 事件的幾種調用方式



          1. //第一種方式    
          2.         Button Btn1 = (Button)findViewById(R.id.button1);//獲取按鈕資源    
          3.         Btn1.setOnClickListener(new Button.OnClickListener(){//創建監聽    
          4.             public void onClick(View v) {    
          5.                 String strTmp = "點擊Button01";    
          6.                 Ev1.setText(strTmp);    
          7.             }    
          8.   
          9.         });   

          1.     //第二種方式(Android1.6版本及以后的版本中提供了,直接在layout中設置)    
          2.     public void Btn3OnClick(View view){    
          3.         String strTmp="點擊Button03";  
          4.         Ev1.setText(strTmp);  
          5.   
          6.     }  

          1.  <Button  
          2.         android:id="@+id/button3"  
          3.         android:layout_width="wrap_content"  
          4.         android:layout_height="wrap_content"  
          5.         android:text="Button3"   
          6.         android:onClick="Btn3OnClick"/>  


          第三種方式 activity 實現 單擊監聽接口

          public class TestButtonActivity extends Activity implements OnClickListener {
          Button btn1, btn2;
          Toast tst;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_test_button);
          btn1 = (Button) findViewById(R.id.button1);
          btn2 = (Button) findViewById(R.id.button2);
          btn1.setOnClickListener(this);
          btn2.setOnClickListener(this);
          }
          @Override
          public void onClick(View v) {
          // TODO Auto-generated method stub
          switch (v.getId()) {
          case R.id.button1:
          tst = Toast.makeText(this, "111111111", Toast.LENGTH_SHORT);
          tst.show();
          break;
          case R.id.button2:
          tst = Toast.makeText(this, "222222222", Toast.LENGTH_SHORT);
          tst.show();
          break;
          default:
          break;
          }
          }
          }




           

          posted @ 2016-11-29 13:31 風人園 閱讀(906) | 評論 (0)編輯 收藏

          打開activity的幾種方式


          一、直接打開,不傳遞參數
          Intent intent = new Intent(this, Activity.class);
          startActivity(intent);


          二、傳遞參數
          public void OpenNew(View v) {
              
          //新建一個顯式意圖,第一個參數為當前Activity類對象,第二個參數為你要打開的Activity類
              Intent intent =new Intent(MainActivity.this,MainActivity2.class);
              
              
          //用Bundle攜帶數據
              Bundle bundle=new Bundle();
              
          //傳遞name參數為tinyphp
              bundle.putString("name""tinyphp");
              intent.putExtras(bundle);
              
              startActivity(intent);       
           //1.要關閉的頁面  
              protected void onCreate(Bundle savedInstanceState) {  
                  
          super.onCreate(savedInstanceState);  
                  setContentView(R.layout.otheractivity);  
                  Intent intent 
          = this.getIntent();  
                  intent.putExtra(
          "tel"12345);  
                  
          //設置requestCode和帶有數據的intent對象  
                  OtherActivity.this.setResult(3, intent);  
                  
          //馬上關閉Activity  
                  this.finish();  
              }
            
                
              
          //2.上面的頁面關閉時,此頁面進行數據的接收  
              class ButtonListener implements android.view.View.OnClickListener{  
                  @Override  
                  
          public void onClick(View arg0) {  
                      Intent intent 
          = new Intent();  
                      intent.setClass(MainActivity.
          this, OtherActivity.class);  
                      
          //與普通的start方法不同,需要設置requestCode  
                      startActivityForResult(intent, 1);  
                  }
            
              }
            
                
              
          //如果要進行此操作,需要在數據接收頁面中復寫activity的onActivityResul()方法  
              @Override  
              
          protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
                  
          super.onActivityResult(requestCode, resultCode, data);  
                  
          int tel = 0;  
                  
          //根據返回碼resultCode來判斷下一步進行的業務代碼  
                  if(resultCode==3){  
                      tel 
          = data.getIntExtra("tel"0);  
                  }
            
                  Log.i(TAG, 
          "tel--------->"+String.valueOf(tel));  
              }
            
           
              }



          三、回傳參數


          posted @ 2016-11-29 13:24 風人園 閱讀(444) | 評論 (0)編輯 收藏

          spring mvc @ExceptionHandler 異常處理

          spring mvc 統一的異常處理,有兩種方式。
          一、exceptionResolver
          二、ExceptionHandler

          兩者不能同時配置。如果配置了第一種,則第二種無效。就因為這個原因,找了一天的問題。

          ExceptionHandler 通過注解的方式,進行配置,只需要在某個controller 中設置了這個注解,則這個controller中的所有異常都會通過這個方法進行處理。

          比如rest controller,增加一個
              @ExceptionHandler
              
          public String exp(HttpServletRequest request, Exception ex) {  
                  
                  Map map 
          = new HashMap();
                  
                  logger.error(
          "error," + UUID.randomUUID().toString(), ex);
                  request.setAttribute(
          "ex", ex);  
                  
                  String msg 
          = ex.getMessage();
                  
                  map.put(
          "success""0"); 
                  map.put(
          "msg", msg);
                  
                  String rtnjson 
          = JSONUtil.objectToJson(map);
                  
                  request.setAttribute(
          "json", rtnjson);
                  
                  
          return "json";
              }
           

          這樣,這個controler中的異常,都會由這個異常處理方法,進行統一處理,生成異常json。避免在各個方法中通過try catch 的方法,進行異常處理。

          posted @ 2016-11-08 08:32 風人園 閱讀(394) | 評論 (0)編輯 收藏

          有關使用 ActionBarSherlock 自定義樣式的問題

          1、不同android 版本,需要設置不同的 sytle 文件。
              默認 通常我們會設置values下面的style 文件
              但是如果是4.0以上,則還需要設置values-v14下面的style文件。
              
          否則不能生效

          posted @ 2014-03-30 09:00 風人園 閱讀(469) | 評論 (0)編輯 收藏

          解決IIS 啟動響應超時 或者 World Wide Web Publishing服務無法啟動提示:錯誤127 找不到指定程序/路徑

          找了很多方案,都說是那個KB939373 這個補丁搞的,但是在添加刪除里就是找不到這個東東,重裝也沒有用,后來找到了這篇文章
          http://www.cnblogs.com/skylaugh/archive/2011/07/21/2112860.html

          根據這篇文章,我把 infocomm.dll 給替換一下,然后就好了,簡直就是坑爹啊。

          這里講講需要注意的事項。
          1、替換的文件通過iis安裝文件生成,請看參考文章
          2、文件直接黏貼覆蓋,不要使用參考里面bat處理。
          3、然后啟動這個服務,啟動iis,搞定

          posted @ 2013-06-18 15:49 風人園 閱讀(231) | 評論 (0)編輯 收藏

          解決Tomcat Error listenerStart 問題

          昨天部署web應用到Tomcat之后,無法成功啟動,并且控制臺沒有詳細的錯誤信息,
          頂多就兩行提示信息,例如:
          嚴重: Error listenerStart
          嚴重: Context [/] startup failed due to previous errors

          或者

          嚴重: Error filterStart
          org.apache.catalina.core.StandardContext start
          嚴重: Context startup failed due to previous errors

          查找logs目錄下的信息,除了這兩句話,也沒別的輔助內容.
          給查錯帶來了困難,在這種情況下,是因為Tomcat自身的默認日志沒有將一些錯誤信息輸出到控制臺或文件,
          這個時候則需要配置Tomcat自身的log,啟用詳細的調試日志.

          3.log4j配置文件:
          log4j.properties
          配置內容為:

          log4j.rootLogger=ERROR,R

          log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
          log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
          log4j.appender.CONSOLE.layout.ConversionPattern=[%p]%t-%c-%m%n

          log4j.appender.R=org.apache.log4j.RollingFileAppender
          log4j.appender.R.File=${catalina.home}/logs/tomcat.log
          log4j.appender.R.MaxFileSize=10MB
          log4j.appender.R.MaxBackupIndex=10
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=[%p]%t-%c-%m%n

          log4j.logger.org.apache.catalina=INFO,R,CONSOLE

          #日志級別不能太低,如果配置為debug的話,輸出的日志信息太多,導致tomcat啟動非常的慢.

          4.Tomcat 6.0所需的juli替換文件:
          http://www.apache.org/dist/--escaped_anchor:079305423cce36d6691457475e081123--/tomcat-6/v6.0.18/bin/extras/tomcat-juli-adapters.jar
          http://www.apache.org/dist/--escaped_anchor:079305423cce36d6691457475e081123--/tomcat-6/v6.0.18/bin/extras/tomcat-juli.jar
          以上兩個鏈接基本沒用,大家可以搜索一下,csdn上面有人提供jar包下載,這里附件也不能加,沒有辦法。

          在Tomcat6.0中,

          將tomcat-juli-adapters.jar,log4j-1.2.15.jar,log4j.properties復制到D:\Java\ApacheTomcat6.0.14\lib下面.

          將tomcat-juli.jar復制到D:\Java\apache-tomcat-6.0.14\bin\下面.

          然后啟動tomcat,就可以在D:\Java\apache-tomcat-6.0.14\logs下看到tomcat.log了.

          在這個時候,再通過日志文件來分析,則會發現出現這種錯誤的情況可能有:
          (以下是我遇到的出錯情況,大多是些低級錯誤)
          1.webapps要用到的classe文件根本沒有復制到WEB-INF/classes目錄下面
          (java.lang.NoClassDefFoundError,而這個信息可能默認沒輸出到控制臺,尤其是用了spring的,昨天就是這個粗心的低級錯誤)
          2.要用到lib文件沒有復制完,缺少lib
          3.lib下的同一個庫的jar文件存在多個不同版本,引起版本沖突.
          4.lib下的jar與tomcat版本不相對應(我遇到的問題是web應用在Tomcat5.5上運行正常,換到Tomcat6.0上就出錯,
          例如一個用了struts的webapp在Tomcat 6上報下面的錯誤
          “Parse Fatal Error at line 17 column 6: The processing instruction
          target matching “[xX][mM][lL]” is not allowed” )

          愿意看英文的可以參考官方網站說明:
          http://tomcat.apache.org/tomcat-6.0-doc/logging.html


          標記一下:) 

          posted @ 2012-04-20 15:39 風人園 閱讀(2879) | 評論 (0)編輯 收藏

          javax.servlet 和 javax.servlet.jsp導致系統錯誤的問題

          提示無法載入 c.tld等信息

          只要刪除 WEB-INF/lib 下的上述兩個文件即可

          因為此文件與 tomcat中的文件版本沖突

          posted @ 2012-04-20 14:16 風人園 閱讀(243) | 評論 (0)編輯 收藏

          [轉]淺談Hibernate的flush機制

          淺談Hibernate的flush機制

          隨著Hibernate在Java開發中的廣泛應用,我們在使用Hibernate進行對象持久化操作中也遇到了各種各樣的問題。這些問題往往都是我們對Hibernate缺乏了解所致,這里我講個我從前遇到的問題及一些想法,希望能給大家一點借鑒。

                這是在一次事務提交時遇到的異常。
                an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
          net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session
          注:非possible non-threadsafe access to the session (那是另外的錯誤,類似但不一樣)
                這個異常應該很多的朋友都遇到過,原因可能各不相同。但所有的異常都應該是在flush或者事務提交的過程中發生的。這一般由我們在事務開始至事務提交的 過程中進行了不正確的操作導致,也會在多線程同時操作一個Session時發生,這里我們僅僅討論單線程的情況,多線程除了線程同步外基本與此相同。
                至于具體是什么樣的錯誤操作那?我給大家看一個例子(假設Hibernate配置正確,為保持代碼簡潔,不引入包及處理任何異常)
          SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
          Session s = sf.openSession();
          Cat cat = new Cat();
          Transaction tran = s.beginTransaction(); (1)
          s.save(cat); (2)(此處同樣可以為update delete)
          s.evict(cat); (3)
          tran.commit(); (4)
          s.close();(5)
                這就是引起此異常的典型錯誤。我當時就遇到了這個異常,檢查代碼時根本沒感覺到這段代碼出了問題,想當然的認為在Session上開始一個事務,通過 Session將對象存入數據庫,再將這個對象從Session上拆離,提交事務,這是一個很正常的流程。如果這里正常的話,那問題一定在別處。
                  問題恰恰就在這里,我的想法也許沒有錯,但是一個錯誤的論據所引出的觀點永遠都不可能是正確的。因為我一直以為直接在對數據庫進行操作,忘記了在我與數據 庫之間隔了一個Hibernate,Hibernate在為我們提供持久化服務的同時,也改變了我們對數據庫的操作方式,這種方式與我們直接的數據庫操作 有著很多的不同,正因為我們對這種方式沒有一個大致的了解造成了我們的應用并未得到預先設想的結果。
          那Hibernate的持久化機制到底有什么不同那?簡單的說,Hibernate在數據庫層之上實現了一個緩存區,當應用save或者update一個 對象時,Hibernate并未將這個對象實際的寫入數據庫中,而僅僅是在緩存中根據應用的行為做了登記,在真正需要將緩存中的數據flush入數據庫時 才執行先前登記的所有行為。
          在實際執行的過程中,每個Session是通過幾個映射和集合來維護所有與該Session建立了關聯的對象以及應用對這些對象所進行的操作的,與我們這 次討論有關的有entityEntries(與Session相關聯的對象的映射)、insertions(所有的插入操作集合)、 deletions(刪除操作集合)、updates(更新操作集合)。下面我就開始解釋在最開始的例子中,Hibernate到底是怎樣運作的。
          (1)生成一個事務的對象,并標記當前的Session處于事務狀態(注:此時并未啟動數據庫級事務)。
          (2)應用使用s.save保存cat對象,這個時候Session將cat這個對象放入entityEntries,用來標記cat已經和當前的會話建 立了關聯,由于應用對cat做了保存的操作,Session還要在insertions中登記應用的這個插入行為(行為包括:對象引用、對象id、 Session、持久化處理類)。
          (3)s.evict(cat)將cat對象從s會話中拆離,這時s會從entityEntries中將cat這個對象移出。
          (4)事務提交,需要將所有緩存flush入數據庫,Session啟動一個事務,并按照insert,update,……,delete的順序提交所有 之前登記的操作(注意:所有insert執行完畢后才會執行update,這里的特殊處理也可能會將你的程序搞得一團糟,如需要控制操作的執行順序,要善 于使用flush),現在cat不在entityEntries中,但在執行insert的行為時只需要訪問insertions就足夠了,所以此時不會 有任何的異常。異常出現在插入后通知Session該對象已經插入完畢這個步驟上,這個步驟中需要將entityEntries中cat的 existsInDatabase標志置為true,由于cat并不存在于entityEntries中,此時Hibernate就認為 insertions和entityEntries可能因為線程安全的問題產生了不同步(也不知道Hibernate的開發者是否考慮到例子中的處理方 式,如果沒有的話,這也許算是一個bug吧),于是一個net.sf.hibernate.AssertionFailure就被拋出,程序終止。

          我想現在大家應該明白例子中的程序到底哪里有問題了吧,我們的錯誤的認為s.save會立即的執行,而將cat對象過早的與Session拆離,造成了 Session的insertions和entityEntries中內容的不同步。所以我們在做此類操作時一定要清楚Hibernate什么時候會將數 據flush入數據庫,在未flush之前不要將已進行操作的對象從Session上拆離。

          對于這個錯誤的解決方法是,我們可以在(2)和(3)之間插入一個s.flush()強制Session將緩存中的數據flush入數據庫(此時 Hibernate會提前啟動事務,將(2)中的save登記的insert語句登記在數據庫事務中,并將所有操作集合清空),這樣在(4)事務提交時 insertions集合就已經是空的了,即使我們拆離了cat也不會有任何的異常了。
          前面簡單的介紹了一下Hibernate的flush機制和對我們程序可能帶來的影響以及相應的解決方法,Hibernate的緩存機制還會在其他的方面給我們的程序帶來一些意想不到的影響。看下面的例子:
          (name為cat表的主鍵)
          Cat cat = new Cat();
          cat.setName(“tom”);
          s.save(cat);
          cat.setName(“mary”);
          s.update(cat);(6)
          Cat littleCat = new Cat();
          littleCat.setName(“tom”);
          s.save(littleCat);
          s.flush();
          這個例子看起來有什么問題?估計不了解Hibernate緩存機制的人多半會說沒有問題,但它也一樣不能按照我們的思路正常運行,在flush過程中會產 生主鍵沖突,可能你想問:“在save(littleCat)之前不是已經更改cat.name并已經更新了么?為什么還會發生主鍵沖突那?”這里的原因 就是我在解釋第一個例子時所提到的緩存flush順序的問題,Hibernate按照insert,update,……,delete的順序提交所有登記 的操作,所以你的s.update(cat)雖然在程序中出現在s.save(littleCat)之前,但是在flush的過程中,所有的save都將 在update之前執行,這就造成了主鍵沖突的發生。
          這個例子中的更改方法一樣是在(6)之后加入s.flush()強制Session在保存littleCat之前更新cat的name。這樣在第二次 flush時就只會執行s.save(littleCat)這次登記的動作,這樣就不會出現主鍵沖突的狀況。再看一個例子(很奇怪的例子,但是能夠說明問 題)
          Cat cat = new Cat();
          cat.setName(“tom”);
          s.save(cat); (7)
          s.delete(cat);(8)
          cat.id=null;(9)
          s.save(cat);(10)
          s.flush();
          這個例子在運行時會產生異常net.sf.hibernate.HibernateException: identifier of an instance of Cat altered from 8b818e920a86f038010a86f03a9d0001 to null這里例子也是有關于緩存的問題,但是原因稍有不同:(7)和(2)的處理相同。(8)Session會在deletions中登記這個刪除動作,同時更新entityEntries中該對象的登記狀態為DELETED。(9)Cat類的標識符字段為id,將其置為null便于重新分配id并保存進數據庫。
          (10)此時Session會首先在entityEntries查找cat對象是否曾經與Session做過關聯,因為cat只改變了屬性值,引用并未改 變,所以會取得狀態為DELETED的那個登記對象。由于第二次保存的對象已經在當前Session中刪除,save會強制Session將緩存 flush才會繼續,flush的過程中首先要執行最開始的save動作,在這個save中檢查了cat這個對象的id是否與原來執行動作時的id相同。 不幸的是,此時cat的id被賦為null,異常被拋出,程序終止(此處要注意,我們在以后的開發過程盡量不要在flush之前改變已經進行了操作的對象 的id)。
          這個例子中的錯誤也是由于緩存的延時更新造成的(當然,與不正規的使用Hibernate也有關系),處理方法有兩種:
          1、在(8)之后flush,這樣就可以保證(10)處save將cat作為一個全新的對象進行保存。
          2、刪除(9),這樣第二次save所引起的強制flush可以正常的執行,在數據庫中插入cat對象后將其刪除,然后繼續第二次save重新插入cat對象,此時cat的id仍與從前一致。
          這兩種方法可以根據不同的需要來使用,呵呵,總覺得好像是很不正規的方式來解決問題,但是問題本身也不夠正規,只希望能夠在應用開發中給大家一些幫助,不對的地方也希望各位給與指正。
            總的來說,由于Hibernate的flush處理機制,我們在一些復雜的對象更新和保存的過程中就要考慮數據庫操作順序的改變以及延時flush是 否對程序的結果有影響。如果確實存在著影響,那就可以在需要保持這種操作順序的位置加入flush強制Hibernate將緩存中記錄的操作flush入 數據庫,這樣看起來也許不太美觀,但很有效。

          http://hi.baidu.com/lkdlhw_2000/blog/item/a35b9cca82945342f31fe769.html

          posted @ 2012-02-22 13:11 風人園| 編輯 收藏

          ActiveMq 的安裝及整合spring 使用


          1、下載 安裝
          在windows xp 上,直接解壓就可以使用
          在2003 上,還需要配置一下,缺一個文件,否則無法啟動

          2、mq 配置
          默認使用 文件持久化的方式,無需進行配置,只需要通過代碼,標記消息為持久化即可

          //設置 消息為 ‘持久化’ 消息,隊列服務器重啟后,會重新載入
          message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
          message.setString("context", context);

          2、整合spring
          mq的spring 配置文件, 此處三個bean
           mq 服務器配置,sender ,監聽器
          完成系統的消息發送和接收

          <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
                  
          <property name="brokerURL" value="tcp://10.10.1.31:61616" />
              
          </bean>
              
              
          <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
                  
          <property name="connectionFactory" ref="connectionFactory" />
              
          </bean>
               
              
          <!--  ============================  消息發送 ============================== -->
              
              
          <!-- ecp.sd.log -->
              
          <bean id="logDestination" class="org.apache.activemq.command.ActiveMQQueue">
                  
          <constructor-arg value="km.wlog"/>
              
          </bean>
              
              
          <bean id="logMessageSender" class="com.chint.mq.sender.LogMessageSender">
                  
          <property name="destination" ref="logDestination" />
                  
          <property name="jmsTemplate" ref="jmsTemplate" />
              
          </bean>
              
              
          <!--=============================  隊列監聽器  ==========================  -->
              
              
          <!-- 日志 隊列監聽器 
              
          <bean id="logContextListener" class="com.chint.mq.listener.LogContextListener">
              
          </bean>
              
              
          <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
                  
          <property name="connectionFactory" ref="connectionFactory"/>
                  
          <property name="destinationName" value="km.wlog"/>
                  
          <property name="messageListener" ref="logContextListener"/>
              
          </bean>
              
          -->

          消息發送者
          @Service
          public class LogMessageSender extends BaseMessageSender{
              
              
          public void sendMessage(final String context) {
                  jmsTemplate.send(destination, 
          new MessageCreator(){

                      @Override
                      
          public Message createMessage(Session session) throws JMSException {
                          MapMessage message 
          = session.createMapMessage();
                          
                          
          //設置 消息為 ‘持久化’ 消息,隊列服務器重啟后,會重新載入
                          message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
                          message.setString(
          "context", context);
                          
                          logger.info(
          "KM INFO [LogMessageSender] send message context ({})", context);
                          
                          
          return message;
                      }

                      
                  }
          );
              }


          }

          消息接受者
          /**
           * 
          @author wxf
           *
           
          */

          public class LogContextListener extends BaseContextListener implements MessageListener{

              @Autowired
              
          private WorkLogManager workLogManager;
              
              @Override
              
          public void onMessage(Message arg) {
                  
          if(arg instanceof MapMessage) {
                      MapMessage message 
          = (MapMessage)arg;
                      
                      
          try {
                          String context 
          = message.getString("context");
                          logger.info(
          "KM INFO [LogContextListener] get message context ({})", context);   
                      }
           catch (JMSException e) {
                          
          throw JmsUtils.convertJmsAccessException(e);
                      }

                  }
           else {
                      System.out.println(arg.toString());
                  }

              }


          }


          以上就完成了 MQ的使用,比較簡單。

          通過spring使用mq從代碼來講還是很簡單的,但是mq的性能可能需要額外的調整一下才能達到最佳的狀態,特別是大數量的情況下。

          僅作記錄

          posted @ 2011-11-09 09:25 風人園 閱讀(633) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 商洛市| 上思县| 武城县| 萨嘎县| 阿巴嘎旗| 儋州市| 乳山市| 胶州市| 确山县| 从化市| 东乡县| 合肥市| 阿拉善盟| 疏附县| 商丘市| 洛宁县| 汉沽区| 惠水县| 乌鲁木齐市| 勐海县| 林口县| 隆子县| 赞皇县| 即墨市| 怀远县| 沅陵县| 正宁县| 墨玉县| 营口市| 马鞍山市| 蓝山县| 永州市| 将乐县| 仲巴县| 夹江县| 阳信县| 漯河市| 中阳县| 阜康市| 商城县| 江华|