风人园

弱水三千,只取一瓢,便能解渴;佛法无边,奉行一法,便能得益。
随笔 - 99, 文章 - 181, 评论 - 56, 引用 - 0
数据加载中……

2009年11月15日

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 风人园 阅读(301) | 评论 (0)编辑 收藏

spring security 参数配置

     摘要:         // 自定义登录页面          http.csrf().disable().formLogin().loginPage("/login")  //指定登录页的路径&n...  阅读全文

posted @ 2018-03-19 20:33 风人园 阅读(421) | 评论 (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 风人园 阅读(373) | 评论 (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 风人园 阅读(248) | 评论 (0)编辑 收藏

android ResourceNotFoundException


在对 TextView 或者 EditText 进行赋值时,调用setText()方法,一定要注意,使用String类型,不要使用int 或者long,否则 会出现找不到资源的异常。系统自动会将int作为一个资源ID,然后去R 里面找,结果找不到。

posted @ 2016-12-21 20:48 风人园 阅读(125) | 评论 (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 风人园 阅读(464) | 评论 (0)编辑 收藏

Android 自定义ListView adapter(zt)

     摘要: http://daoshud1.iteye.com/blog/1874241 本文讲实现一个自定义列表的Android程序,程序将实现一个使用自定义的适配器(Adapter)绑定 数据,通过contextView.setTag绑定数据有按钮的ListView。 系统显示列表(ListView)时,首先会实例化一个适配器,本文将实例化一个自定义的适配器。实现 自定义适...  阅读全文

posted @ 2016-12-01 13:13 风人园 阅读(156) | 评论 (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 风人园 阅读(171) | 评论 (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 风人园 阅读(143) | 评论 (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 风人园 阅读(150) | 评论 (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 风人园 阅读(894) | 评论 (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 风人园 阅读(433) | 评论 (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 风人园 阅读(382) | 评论 (0)编辑 收藏

有关使用 ActionBarSherlock 自定义样式的问题

1、不同android 版本,需要设置不同的 sytle 文件。
    默认 通常我们会设置values下面的style 文件
    但是如果是4.0以上,则还需要设置values-v14下面的style文件。
    
否则不能生效

posted @ 2014-03-30 09:00 风人园 阅读(458) | 评论 (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 风人园 阅读(223) | 评论 (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 风人园 阅读(2867) | 评论 (0)编辑 收藏

javax.servlet 和 javax.servlet.jsp导致系统错误的问题

提示无法载入 c.tld等信息

只要删除 WEB-INF/lib 下的上述两个文件即可

因为此文件与 tomcat中的文件版本冲突

posted @ 2012-04-20 14:16 风人园 阅读(233) | 评论 (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 风人园 阅读(624) | 评论 (0)编辑 收藏

同一台电脑登陆多个账号的问题

这个问题一直比较奇怪,今天搜了一下,原来是浏览器的问题,这让我想起来了网页版的网游,不能多登的问题。原来session是相同的。

打开的是两个浏览器还是两个页签,
比如 IE7这种支持多页签的,也就是在一个浏览器里面同时打开多个页签的这种,是共用一个Session的,
但是比如IE6这种一次只能打开一个浏览器的,就没有问题,

因为打开的是多个浏览器我说了,这个和浏览器相关,每当你打开一个浏览器,这个浏览器就会有专门的session.


也算是解决了一个问题吧:)

这里标记一下

posted @ 2011-09-09 16:43 风人园 阅读(408) | 评论 (0)编辑 收藏

遍历所有数据文件的大小

 

1、新建一个临时数据库,用于存放查询结果
CREATE TABLE DatabaseFileLog
(
 date DATETIME,
 dbname VARCHAR(20),
 FILENAME VARCHAR(100),
 fileSIZE FLOAT
 
)


2、通过游标遍历所有数据库
declare @dbName varchar(50)
declare @command varchar(1024)
declare dbName_cursor CURSOR FOR
    select [name]
    from master.dbo.sysdatabases
    where [name] not in ('master','tempdb','msdb','model')
open dbName_cursor
FETCH NEXT FROM dbName_cursor INTO @dbName
WHILE @@FETCH_STATUS = 0
begin
    set @command = '
        insert into DatabaseFileLog
        select
        getdate(),
        '''+
        @dbName
        +''',

        filename,
        convert(float,size) * (8192.0/1024.0)/1024.0 as ''MB''

        from '+@dbName +'.dbo.sysfiles ';
    exec ( @command );
    FETCH NEXT FROM dbName_cursor INTO @dbName ;
end
CLOSE dbName_cursor;
DEALLOCATE dbName_cursor;

3、查询结果
SELECT * FROM DatabaseFileLog

posted @ 2011-09-06 10:46 风人园 阅读(207) | 评论 (0)编辑 收藏

eclipse 注释模版 设置


设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后展开Comments节点就是所有需设置注释的元素啦。

常用的,一般两个

文件(Files)注释标签:

/**  
* @Title: ${file_name}
* @Package ${package_name}
* @Description: ${todo}(用一句话描述该文件做什么)
* @author A18ccms A18ccms_gmail_com  
* @date ${date} ${time}
* @version V1.0  
*/


类型(Types)注释标签(类的注释):

/**
* @Description: ${todo}(这里用一句话描述这个类的作用)
* @author ${user}
* @date ${date} ${time}
*
* ${tags}
*/

posted @ 2011-08-18 16:30 风人园 阅读(344) | 评论 (0)编辑 收藏

Spring MVC 使用中的注意事项

    ModelAndView中保存了要传递给视图的对象和具体要使用的视图文件,自2.0起, Spring MVC提供了Convention over Configuration的机制,大大简化了代码与配置。简单地说,名字以Controller结尾的控制器类都会被映射为相应的地址,ListArticleController对应/listarticle*,如果是MultiActionController则会被映射为一个目录;向ModelAndView添加对象时可以不用指定键(key),单一对象的键取决于类名,比如x.y.User的键是user,而某一类对象的 Set、List或数组则稍有些复杂,取第一个对象的类名加上“List”作为它的键,比如这里的articles是一个存放Article对象的 List,它的键就是articleList;
也可以通过执行key,来指定变量名称

posted @ 2010-12-30 15:51 风人园 阅读(369) | 评论 (0)编辑 收藏

spring 事务的回滚问题

    spring的事物配置,默认状态下,只针对 RuntimeException 进行回滚。
而像SQLException并不是RuntimeException,所以这里需要特别注意。

这里困扰了我很久,一直没有想明白为什么在一个事务里面,部分成功,部分失败。可能就是这个原因导致的。
也就是说,一些系统级别的异常,前期都需要转化成 RuntimeException 。这样就可以进行回滚了。

但是这样的只需要修改底层,另外一个偷懒的方法,在每个service类上直接指定rollback = Exception.class。这样所有的异常都会回滚。但是这样有没有副作用,但是不清楚。

异常一直是我没有搞定的一块内容之一,称这个机会研究一下。
为什么需要分check 和unckeck,两者有什么不动点。
如果都是用uncheck,会不会有什么问题?
待续。。。

posted @ 2010-12-14 14:01 风人园 阅读(859) | 评论 (1)编辑 收藏

hibernate 关联查询错误(Path expected for join)

    以前没怎么用,现在真用起来的时候还是会有很多白痴问题,哈。
    今天想做一个left join , 关联关系应该是已经配好了,但是调用hql就是报错,也不知道怎么回事。继续研究ing。

posted @ 2009-12-10 14:00 风人园 阅读(4899) | 评论 (1)编辑 收藏

Hibernate主从数据的操作

struts2+spring2.5+hibernate 3.3

在hibernate的操作中,特别是主从数据的操作。

一般有这么几个地方需要注意,以前也一直没有拿hibernate好好用过,现在真正用起来,问题还是挺多了。这几天一直在调试解释这种问题。

主数据中的一对一关联,这里的关联数据从页面提交的时候是否可以直接映射到主数据对象中?暂时不清楚,可以测试一下。

然后是明细数据的操作,现在动态产生的行数据,然后手动解析,生成明细对象。整个过程个人感觉比较麻烦,暂时也想不出有什么好的解决方案。

这里在级联保存数据的时候,首先要清除掉原来的明细数据,然后再把页面提交过来的数据加上。
不知道一般是不是这样弄的。否则没法清楚原来的数据。


posted @ 2009-11-17 19:30 风人园 阅读(351) | 评论 (0)编辑 收藏

通过MyEclipse生成annotation方式的entity类

    通过搜索和阅读myEclipse的帮助文件,发现这是可以实现的。不过前提是,你使用的hibernate是3.2版本。这样就可以支持以注解的方式生成实体类了。跟hbm配制文件方式基本是一样的。

    昨天特地好好的看了一下MyEclipse的帮助,里面关于ajax web开发的工具感觉还是挺好用的,以前一直也没有了解一下里面的功能,以后要好好用一下,还是可以有不少帮助的。
    今天先起个头,明天写一个详细的操作说明,这样也方便自己,免得忘了。

posted @ 2009-11-15 19:02 风人园 阅读(494) | 评论 (0)编辑 收藏