存档

文章标签 ‘Java’

org.hibernate.SessionException: Session is closed! 异常解决方法

2010年4月29日 IT北瓜 6 条评论

刚刚在程序中出现了org.hibernate.SessionException: Session is closed! 这个异常,查看Firebug控制台,还能发现有这样的异常信息org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction;记录一下解决方法。

程序代码如下:

public boolean activityUpdate(Activity activity) throws Exception {

	Session session = null;
	Transaction tran = null;

	boolean r = false;

	try{
		//创建sql
		String sql1 = "delete from Activityfilm where activityid=" + activity.getId();//删除活动影片数据
		String sql2 = "delete from Activityclient where activityid=" + activity.getId();//删除活动客户数据

		//获得session
		session = this.getSession();
		//开始事务
		tran = session.beginTransaction();
		//执行删除操作
		int del_1 = session.createSQLQuery(sql1).executeUpdate(), del_2 = session.createSQLQuery(sql2).executeUpdate();
		System.out.println("del_1: "+ del_1 + "###del_2: " + del_2);
		//更新活动
		session.update(activity);
		if(del_1 > 0 && del_2 > 0){
			r = true;
		}else{
			r = false;
		}
		System.out.println("r: "+ r);
		tran.commit();
		if(!r){//执行回滚
			System.out.println("执行回滚#####################");
			tran.rollback();
		}
	}catch(Exception ex){
		if(tran != null){
			System.out.println("执行回滚@@@@@@@@@@@@@@@@@@@@@");
			tran.rollback();
		}
		ex.printStackTrace();
	}finally{
		if(tran != null){
			System.out.println("设置事务为null");
			tran = null;
		}
		if(session != null){
			System.out.println("关闭session$$$$$$$$$$$$$$$$$");
			session.close();//执行这一行总是报异常:org.hibernate.SessionException: Session is closed! 
		}
	}
	System.out.println("返回: "+ r);
	return r;

}

引用网上的资料:

先看看SessionFactory.getCurrentSession与openSession的区别

1. 如果使用的是getCurrentSession来创建session的话,在commit后,session就自动被关闭了,

    也就是不用再session.close()了。但是如果使用的是openSession方法创建的session的话,

    那么必须显示的关闭session,也就是调用session.close()方法。这样commit后,session并没有关闭

/*2. getCurrentSession的使用可以参见hibernate\hibernate-3.2\doc\tutorial\src项目

3. 使用SessionFactory.getCurrentSession()需要在hibernate.cfg.xml中如下配置:

   * 如果采用jdbc独立引用程序配置如下:

    <property name="hibernate.current_session_context_class">thread</property>

   * 如果采用了JTA事务配置如下

    <property name="hibernate.current_session_context_class">jta</property>*/

将以上程序中的:

//获得session
session = this.getSession();

修改为:

//获得session
session = this.getHibernateTemplate().getSessionFactory().openSession();

这样异常就解决了。

java中从含反斜杠路径截取文件名的方法

2009年12月19日 IT北瓜 没有评论

      例如:获取到的文件路径为C:\Documents and Settings\Leeo\My Documents\logo.gif

      现在想要取得图片的名称logo.gif,我们知道反斜杠“\”是转义字符,所以不能直接

String temp[] = filePath.split("\");//filePath的值就是上面的文件路径

      来分割文件路径,而应该这样写

/*
 *java中\\表示一个\,而regex中\\也表示\,
 *所以当\\\\解析成regex的时候为\\
 **/
String temp[] = filePath.split("\\\\");

      在Linux系统中

System.getProperty("file.separator", "\\")

      输出为“/”,而在Windows系统中输出为“\”,所以要兼容两者可以这么写

String temp[] = filePath.replaceAll("\\\\","/").split("/");

      获取文件名称的完整代码如下:

String temp[] = filePath.replaceAll("\\\\","/").split("/");
String fileName = ""
if(temp.length > 1){
    fileName = temp[temp.length - 1];
}
分类: Java 标签: , ,

Struts2+FlashFileUpload文件上传并生成缩略图和添加水印

2009年11月6日 IT北瓜 21 条评论

      以前用过SWFUpload,功能确实很强大。javaeye上有人发布了这样一篇文章step-by-step多文件WEB批量上传(swfupload)的完美解决方案有兴趣的朋友可以看一下。Leeo觉得SWFUpload稍微不足的就是界面的定制,总感觉自己定制出来的界面有点难登大雅之堂。下面Leeo为大家介绍一下,如何使用FlashFileUpload这个Flash组件来实现多文件上传,并且通过java程序自动生成缩略图和添加水印,FlashFileUpload定制出来的界面还是挺漂亮的(PS:这个界面是Leeo从UUShare上弄下来的,^_^),先来Show一张效果图:

      从上面的图片从可以看出中间有个水印(PS:本博客的Logo),这并不是用Photoshop之类的软件弄上去的,而是通过下面将要讲到的java程序自动添加的,效果很不错,(*^__^*) 嘻嘻……好,正式开始吧…

      第一步:当然是获取flashfileupload.swf这个Flash组件啦,大家可以从这里下载,或者其他什么途径得到都行

      第二步:编写上传页面的代码如下:

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
  String uploadType = (String)request.getParameter("uploadType");
  Long filmid = Long.parseLong((String)request.getParameter("filmid"));
  //out.print(uploadType);
  //out.print(filmid);
%>
<object id="fileUpload"
    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab#version=10,0,22,87"
    height="310" width="500" align="middle"
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">
    <param name="_cx" value="13229" />
    <param name="_cy" value="8202" />
    <%
        if("Video".equals(uploadType)){
    %>
    <param name="flashvars" value="fileTypeDescription=允许视频格式&fileTypes=*.asx;*.asf;*.mpg;*.wmv;*.3gp;*.mp4;*.mov;*.avi;*.flv;*.wmv9;*.rm;*.rmvb&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>" />
    <%
        }else{
    %>
    <param name="flashvars" value="fileTypeDescription=JPG格式图片&fileTypes=*.jpg;*.jpeg&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>" />
    <%
        }
    %>
    <param name="movie" value="flashfileupload.swf?ver=20090520" />
    <param name="src" value="flashfileupload.swf?ver=20090520" />
    <param name="wmode" value="transparent" />
    <param name="play" value="0" />
    <param name="loop" value="-1" />
    <param name="quality" value="high" />
    <param name="salign" value="lt" />
    <param name="menu" value="-1" />
    <param name="base" value="" />
    <param name="allowscriptaccess" value="sameDomain" />
    <param name="scale" value="noscale" />
    <param name="devicefont" value="0" />
    <param name="embedmovie" value="0" />
    <param name="bgcolor" value="" />
    <param name="swremote" value="" />
    <param name="moviedata" value="" />
    <param name="seamlesstabbing" value="1" />
    <param name="profile" value="0" />
    <param name="profileaddress" value="" />
    <param name="profileport" value="0" />
    <param name="allownetworking" value="all" />
    <param name="allowfullscreen" value="true" />
    <%
        if("Video".equals(uploadType)){
    %>
    <embed src="flashfileupload.swf?ver=20090520"
        flashvars="fileTypeDescription=允许视频格式&fileTypes=*.asx;*.asf;*.mpg;*.wmv;*.3gp;*.mp4;*.mov;*.avi;*.flv;*.wmv9;*.rm;*.rmvb&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>"
        quality="high"
        wmode="transparent"
        width="500"
        height="310"
        name="fileUpload"
        align="middle"
        allowscriptaccess="samedomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer">
    </embed>
    <%
        }else{
    %>
    <embed src="flashfileupload.swf?ver=20090520"
        flashvars="fileTypeDescription=JPG格式图片&fileTypes=*.jpg;*.jpeg&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>"
        quality="high"
        wmode="transparent"
        width="500"
        height="310"
        name="fileUpload"
        align="middle"
        allowscriptaccess="samedomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer">
    </embed>
    <%
        }
    %>
</object>

说明:其中主要的是flashvars这个参数的设置(PS:Leeo本人对这里的设置也仅仅是略知一二)

fileTypeDescription:允许上传文件的类型描述

fileTypes:允许上传的文件类型

completeFunction:上传完成后调用的js函数

fileSizeLimit:文件大小限制

totalUploadSize:一次性上传文件总大小限制

accounttype:这个没搞清楚怎么用,如果哪位知道的请告知一声,谢谢…

uploadPage:上传文件的请求路径,跟在它后面的是一些用户附加的数据。其中网上有网友说可以;jsessionid=的形式传递session,Leeo没有做测试。?uploadType=是程序中需要的一些附加数据,这里本来需要两个变量的,之所以把它写到一个变量里,然后用“-”隔开两个变量值,就像代码中的<%=uploadType %>-<%=filmid %>,是因为我们知道通常通过url传参是用“&”号隔开的,但这里却不能这么做,因为整个flashvars就是用“&”来隔开不同参数的,如果附加的数据也用“&”隔开就会被截断,得不到我们想要的数据,所以这里用一种比较马虎的解决方法,利用“-”号把不同变量值连接起来,然后在服务器端的java代码中用split("-")再把它们分割开来

    第三步:配置struts.xml文件,如下:

<package name="ajaxfileupload" namespace="/" extends="ajaxfileupload-default">
	<action name="flashupload" class="leeo.action.FlashfileuploadAction">
		<result name="success" type="httpheader">
			<param name="status">200</param>
		</result>
	</action>
</package>

特别说明:这里还用到了ajax-file-upload-plugin-0.4.0.jar(PS:Struts2中用ajxa方式上传文件需要的jar包)

      第四步:编写action类代码,如下:

/** 文件对象 */
private transient File[] Filedata;
/** 文件名 */
/** 文件对象 */
private transient File[] Filedata;
/** 文件名 */
private transient String[] FiledataFileName;
/** 文件内容类型 */
private transient String[] FiledataContentType;

/**
 * 区分是上传海报、剧照、片花
 * **/
private transient String uploadType;

public String Upload() throws Exception {
	System.out.println("FiledataFileName length:" + FiledataFileName.length);
	System.out.println("uploadType:" + uploadType);
	String[] type_filmid = uploadType.split("-");
	System.out.println("filmid:" + type_filmid[1]);

	Film f = filmService.findFilmById(new Long(type_filmid[1]));
	//原文件存放路径  
	String OriginalImageDirectory = ServletActionContext.getServletContext().getRealPath("/UploadFile/" + type_filmid[0] + "/OriginalImage") + System.getProperty("file.separator", "\\");
	for(int i = 0; i < Filedata.length; i ++){
		System.out.println("Filedata["+i+"]:" + Filedata[i]);
		System.out.println("FiledataFileName["+i+"]:" + FiledataFileName[i]);
		System.out.println("FiledataContentType["+i+"]:" + FiledataContentType[i]);

        //在指定目录创建文件
        String newname = FileUpload.getFileName(FiledataFileName[i]);
        File bigFile = new File(OriginalImageDirectory, newname);
        //把要上传的文件copy过去 
        FileUpload.copy(Filedata[i], bigFile);

        if(!"Video".equals(type_filmid[0])){
        	//缩略图存放路径
			String ThumbnailsDirectory = ServletActionContext.getServletContext().getRealPath("/UploadFile/" + type_filmid[0] + "/Thumbnails") + System.getProperty("file.separator", "\\");
			//生成缩略图
			FileUpload.scaleImage(OriginalImageDirectory + newname, ThumbnailsDirectory + newname, 180, 200);
			//设置数据库海报字段路径

			String waterImgFile = ServletActionContext.getServletContext().getRealPath("/UploadFile") + System.getProperty("file.separator", "\\");
	        // 给大图添加文字水印  
	        //FileUpload.watermark(bigFile);  
	        // 给大图添加图片水印,可以是gif或png格式  
	        FileUpload.imageWaterMark(bigFile, waterImgFile);
			File smallFile = new File(ThumbnailsDirectory, newname);
			// 给大图添加文字水印  
	        //FileUpload.watermark(smallFile);  
	        // 给大图添加图片水印,可以是gif或png格式  
	        FileUpload.imageWaterMark(smallFile, waterImgFile);
        }

        /*
         * 操作数据库部分
         * */
        if("Poster".equals(type_filmid[0])){
        	f.setFPoster(newname);
        	filmService.modFilm(f);
        }else if("Still".equals(type_filmid[0])){
        	FilmStill fs = new FilmStill();
        	fs.setFsPath(newname);
        	fs.setFilm(f);
        	filmService.addFilmStill(fs);
        }else if("Video".equals(type_filmid[0])){
        	FilmVideo fv = new FilmVideo();
        	fv.setFvPath(newname);
        	fv.setFilm(f);
        	filmService.addFilmVideo(fv);
        }
	}
	return SUCCESS;
}

public File[] getFiledata() {
	return Filedata;
}

public void setFiledata(File[] filedata) {
	this.Filedata = filedata;
}

public String[] getFiledataFileName() {
	return FiledataFileName;
}

public void setFiledataFileName(String[] filedataFileName) {
	this.FiledataFileName = filedataFileName;
}

public String[] getFiledataContentType() {
	return FiledataContentType;
}

public void setFiledataContentType(String[] filedataContentType) {
	this.FiledataContentType = filedataContentType;
}

public String getUploadType() {
	return uploadType;
}

public void setUploadType(String uploadType) {
	this.uploadType = uploadType;
}

其中,操作数据库部分的代码跟这个例子无关,可以省去。

      第五步:要用到的其他类的代码(PS:这部分代码来自互联网)

      1:FileUpload.java用于生成缩略图、添加水印、生成无重复的文件名

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class FileUpload {

	private static final int BUFFER_SIZE = 16 * 1024;
	private static final String WATER_TEXT = "文字水印";
	private static final String WATER_IMG_NAME = "logo.png";

	/*生成无重复文件名*/
    public static String getFileName(String name){

		SimpleDateFormat df =new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = new Date();
		String filename=null;
		if(!"".equals(name) && name != null){
			filename=df.format(date) + RandomNum.random2() + name.substring(name.lastIndexOf("."), name.length());
		}
		System.out.println("filename is:"+filename);
		return filename;
	}

    /*上传文件*/
	public static void copy(File src, File dst) {
        try {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);
                out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE);
                byte[] buffer = new byte[BUFFER_SIZE];
                while (in.read(buffer) > 0) {
                    out.write(buffer);
                }
            } finally {
                if (null != in) {
                    in.close();
                }
                if (null != out) {
                    out.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	/*生成缩略图*/
	public static String scaleImage(String fromFileStr, String saveToFileStr, int formatWideth, int formatHeight) throws Exception {
		ScaleImage is = new ScaleImage();
		try {
			is.saveImageAsJpg(fromFileStr, saveToFileStr, formatWideth, formatHeight);
        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "error";
        }
        return "ok";
	}

	/**
	     * 添加文字水印
	     *
	     * @return
	     * @throws Exception
	     * @throws Exception
	     */
	    public static void watermark(File img) throws Exception {
	        System.out.println("[watermark file name]--" + img.getPath());
	        try {  

	            if (!img.exists()) {
	                throw new IllegalArgumentException("file not found!");
	            }  

	            System.out.println("[watermark][img]--" + img);  

	            // 创建一个FileInputStream对象从源图片获取数据流  
	            FileInputStream sFile = new FileInputStream(img);  

	            // 创建一个Image对象并以源图片数据流填充  
	            Image src = ImageIO.read(sFile);  

	            // 得到源图宽  
	            int width = src.getWidth(null);
	            // 得到源图长  
	            int height = src.getHeight(null);  

	            // 创建一个BufferedImage来作为图像操作容器  
	            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	            // 创建一个绘图环境来进行绘制图象  
	            Graphics2D g = image.createGraphics();
	            // 将原图像数据流载入这个BufferedImage  
	            System.out.println("width:" + width + " height:" + height);
	            g.drawImage(src, 0, 0, width, height, null);
	            // 设定文本字体  
	            g.setFont(new Font("宋体", Font.BOLD, 28));
	            String rand = WATER_TEXT;
	            // 设定文本颜色  
	            g.setColor(Color.blue);
	            // 设置透明度  
	            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
	            // 向BufferedImage写入文本字符,水印在图片上的坐标  
	            g.drawString(rand, width - (width - 20), height - (height - 60));
	            // 使更改生效  
	            g.dispose();
	            // 创建输出文件流  
	            FileOutputStream outi = new FileOutputStream(img);
	            // 创建JPEG编码对象  
	            JPEGImageEncoder encodera = JPEGCodec.createJPEGEncoder(outi);
	            // 对这个BufferedImage (image)进行JPEG编码  
	            encodera.encode(image);
	            // 关闭输出文件流  
	            outi.close();
	            sFile.close();  

	        } catch (IOException e) {
	            e.printStackTrace();
	            throw new Exception(e);
	        }
	    }  

	    /**
	     * 添加图片水印
	     *
	     */
	    public static void imageWaterMark(File imgFile, String waterFilePath) throws Exception {
	        try {
	            // 目标文件  
	            Image src = ImageIO.read(imgFile);
	            int wideth = src.getWidth(null);
	            int height = src.getHeight(null);
	            BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
	            Graphics2D g = image.createGraphics();
	            g.drawImage(src, 0, 0, wideth, height, null);  

	            // 水印文件 路径  
	            String waterImgPath = waterFilePath + WATER_IMG_NAME;
	            System.out.println("waterImgPath--" + waterImgPath);
	            File waterFile = new File(waterImgPath);
	            Image waterImg = ImageIO.read(waterFile);  

	            int w_wideth = waterImg.getWidth(null);
	            int w_height = waterImg.getHeight(null);
	            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
	            g.drawImage(waterImg, (wideth - w_wideth) / 2, (height - w_height) / 2, w_wideth, w_height, null);
	            // 水印文件结束  

	            g.dispose();
	            FileOutputStream out = new FileOutputStream(imgFile);
	            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
	            encoder.encode(image);
	            out.close();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
}

      2:RandomNum.java用于生成无重复随机数

import java.util.Random;

public class RandomNum {

	public static int[] random1() {
		Random r = new Random();
		int temp1, temp2;
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
		int len = send.length;
		int returnValue[] = new int[22];
		for (int i = 0; i < 22; i++) {
			temp1 = Math.abs(r.nextInt()) % len;
			returnValue[i] = send[temp1];
			temp2 = send[temp1];
			send[temp1] = send[len - 1];
			send[len - 1] = temp2;
			len--;
		}
		return returnValue;
	}
	public static int[] random2() {
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
		int temp1, temp2, temp3;
		Random r = new Random();
		for (int i = 0; i < send.length; i++){// 随机交换send.length次
			temp1 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生一个位置
			temp2 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生另一个位置
			if (temp1 != temp2) {
				temp3 = send[temp1];
				send[temp1] = send[temp2];
				send[temp2] = temp3;
			}
		}
		return send;
	}
}

      到此,本应用实例的代码就完成了,赶紧体验一下吧。。。

Hibernate3.3.2+Spring2.5.6+Struts2.1.6整合异常解决——不断更新

2009年9月24日 IT北瓜 5 条评论

1、org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ’sessionFactory’ is defined

异常说明:sessionFactory bean未定义

异常原因:applicationContext.xml配置文件中使用其他名字sessionFactory

<property name="sessionFactory">
    <ref bean="dmccSessionFactory"/>
</property>

上面的代码中bean=”dmccSessionFactory”,这是造成异常的原因。这里用了别名,而不是默认的bean=”sessionFactory”。这种情况下在web.xml文件中配置OpenSessionInViewFilter则需要对使用的别名进行声明。

<filter>
    <description>处理Hibernate的懒加载问题</description>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <description>默认情况下,这个Filter会在Spring的bean池中找一个叫做sessionFactory的bean。如果使用了其他名字的SessionFactory,则应该在这里 指定这个名字。</description>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>dmccSessionFactory</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2、

ERROR – failed to lazily initialize a collection of role: leeo.pojo.TPermission.roles, no session or session was closed

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: leeo.pojo.TPermission.roles, no session or session was closed

异常说明:session已关闭,无法初始化懒加载数据集role

异常原因:Hibernate映射文件中配置了lazy="true",同时也启用了OpenSessionInViewFilter。当实现ajax检测role名称是否可用时报以上异常,我这里检测role名称是利用json格式返回数据的。json返回数据的特点是:如果action中的属性有get()方法并且该属性没有transient修饰,那么json就会将其返回。在我的TRoleAction中有private TRole role;并且role有get()方法,所以在检测名称是否可用后返回的json数据中会将这一属性返回,但是检测名称的可用性根本不需要用到这个属性,异常就是由于启用懒加载机制下json中返回role这个属性需要查询数据库,而这时session已经关闭,因此报异常。

解决方法:用transient对role属性进行修饰,即:private transient TRole role;这样json就不会将其返回,因为也不用再次查询关联数据不会出现session已关闭的异常。