◎筱米加步枪◎.Blog

Happy coding

Oracle 树状查询

在实际应用中,经常利用数据库保存树状结构的数据,通常用一张表中的两个字段表示,一个是自身的ID,一个是保存父类的ID。在这样具有这种关系中的数据,要求查出的数据具有我们想要的树状显示。这里需要引入Oracle的一个查询语句。

Select  *  from tablename
  start with [condition1]
  Connect By Prior  [condition2]
  where [condition3] 

condition1 通常是用于筛选某颗树或者多颗树的结点,这里所的树包括子树,

condtion2 通常是用于连接父结点和子结点的关系,prior 所表示的是上一条记录,通常用法:prior id = pid,(上一条的的ID号是本条记录的父类ID号)这样就把整个树状结构给建立起来了。

conditon3 就是我们通常的where语句,过滤某些记录。

现在看下具体例子。

其中Test_ID 表示本身的ID,Test_PID表示父类的ID

这边记录的描述成树状结构就是如下:

现在,假设我们查询的福州以及福州下的所有子东西,就可以这样查询,

只要取福州的根结点就可以,福州的根结点翻译成数据库中存的数据就是 test_id =1

因此得到的sql如下:

Select * From Test_ t 
  Start With Test_Id = 1
  Connect By Prior Test_Id = Test_Pid

查询结果:

用结构图表示就是如下信息:

因此想要查询某些信息,只要抓住根结点的条件就可以。。Over~~

Java深克隆(序列化方式)

对于Java的克隆技术,标准的方式是:首先实现Cloneable接口,然后重写clone方法,调用父类clone进行克隆。

介绍另外一种方法,该方法的原理:

利用流将序列化的对象写在流里,因为写在流里面的对象就是原对象的一份拷贝,而原对象还在Java虚拟机里(JVM)里,再从流里面读取出来得到的对象就是得到一份克隆对象。

注意:需要克隆的对象必须实现Serializable接口

接着之前的场景,看下面的例子:

public class User implements Serializable{
	
	private static final long serialVersionUID = 1L;

	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public Object copy() throws IOException, ClassNotFoundException{
		//将对象序列化后写在流里,因为写在流里面的对象是一份拷贝,
		//原对象仍然在JVM里
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);
		oos.writeObject(this);
		
		ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
				bos.toByteArray()));
		return ois.readObject();
	}
}
public class Address implements Serializable{
	
	private static final long serialVersionUID = 1L;
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}
}
/**
 * 测试克隆-深克隆(使用序列化的方式进行深克隆)
 * 深克隆不但克隆当前的对象,而且还克隆该对象所引用的对象
 * @author CST
 */
public class TestClone {

	public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
		User chen = new User("CST");
		chen.setAddress(new Address("福州"));
		
		User liu = (User) chen.copy();
		liu.setUserName("LXF");
		liu.getAddress().setAddressName("泉州");
		System.out.println(chen.getUserName()+"="+chen.getAddress().getAddressName());
	}
}

输出结果:CST=福州
效果同实现Cloneable接口方式一样

Java克隆技术

前些天,根据需要,加入了克隆技术,学习了下,总结如下:

Java的对象都是引用,当将一个对象赋值给另外一个对象的时候,也就是说指针(当然,java没有指针的概念)同指向同一块内存地址,这个时如果对一个对象进行修改,也必然会修改另外一个对象的值,这明显不是我们想要的,解决这个问题,可以引入克隆技术,我们可以克隆一个对象出来,使得对克隆出来的对象修改不会改变原始对象的值。

克隆分为:浅克隆和深克隆。

浅克隆是指:浅克隆只是克隆当前的对象,不克隆该对象所应用的对象

深克隆是指:深克隆不但克隆当前的对象,而且还克隆该对象所引用的对象

看具体实例:

(模拟场景:用户对象、地址对象、用户对象拥有地址对象)

一、浅克隆

//克隆必须实现Cloneable,调用父类的clone()方法
public class User implements Cloneable{
	
	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	/*
	 * 克隆当前对象,得到克隆后的对象
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
//地址对象
public class Address{ 
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}
}
/**
 * 测试克隆-浅克隆
 * 浅克隆只是克隆当前的对象,不克隆该对象所应用的对象
 * @author CST
 */
public class TestClone {

	public static void main(String[] args) throws CloneNotSupportedException {
		User chen = new User("CST");
		chen.setAddress(new Address("福州"));
		
		User liu = (User) chen.clone();
		liu.setUserName("LXF");
		liu.getAddress().setAddressName("泉州");
		System.out.println(chen.getUserName()+"="+chen.getAddress().getAddressName());
	}
}

输出结果:CST=泉州

可以看到,虽然User对象可以单独操作,但是视图去修改User下的Address值,仍然是改变了原始用户下的Address值

二、深克隆:

public class User implements Cloneable{
	
	private String userName;

	private Address address;
	
	public User(String userName) {
		super();
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	//克隆
	@Override
	public Object clone() throws CloneNotSupportedException {
		//克隆对象的同时,也克隆user下的应用对象Address
		User user = (User) super.clone();
		Address address = (Address) user.getAddress().clone();
		user.setAddress(address);
		return user;
	}
}
public class Address implements Cloneable{
	
	private String addressName;
	
	public Address(String addressName) {
		super();
		this.addressName = addressName;
	}

	public String getAddressName() {
		return addressName;
	}

	public void setAddressName(String addressName) {
		this.addressName = addressName;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

测试类同上,

输出结果:CST=长乐

这样,才是我们想要的结果。无论修改当前对象还是当前对象所包含的对象,都是两个独立的操作,互不影响。

No Hibernate Session bound to thread,and configuration does not allow creation错误解决方案

忽遇如下错误:

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

百度得解:

因:将对应操作入事务即可

方法:于Spring配置文件的事务拦截器中加入对应的类即可~

开发简单请假流程DEMO时知识和错误汇总

搞了将近一周,才把这个请假流程给搞定,在这期间遇到的问题N多,其实很感慨的说Struts2的组件超难用的,组件连把布局都加进去了,超郁闷的,不过为了熟悉下struts2还是硬着头皮用了。有涉及到的技术是Struts2+Jbpm4.3.总结下,遇到的问题以及解决方案,以及一些小知识。

①.Struts2部分。

 

  1.Struts2的组件:下拉单选框,存放ValueName是通过list属性。

   list="#{Value1:Name1,Value2:Name2...}" 

     例如:<struts:select name="identity"

           list="#{'personnel':'员工','manager':'经理','boss':'老板'}" />

 

  2.struts.xml配置中,action结点下的result配置,如果result是指向另外一个Action,需指定属性 

   type="redirectAction"

    例如:

    <result name="manager" type="redirectAction">/showTask.action</result>

 

  3.Struts2中的requestresponse以及Session获取方式:

private ActionContext context = ActionContext.getContext();

//获取Request

private HttpServletRequest request = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST);

//获取Response

private HttpServletResponse response = (HttpServletResponse) context.get(ServletActionContext.HTTP_RESPONSE);

//获取Session

private Map<String,Object> session = context.getSession();

 

   4.表单的属性名会通过set方法传入到action中的属性名,action处理的结果通过相应的get方法来传入到页面上。就不用像以前Struts1那样通过ActionForm来传递了

   5.struts2的标签获取session中的值,

   如:<struts:property value="#session.loginUser.name"/>

 

   6.访问出错:No result defined for action XXX and result success

       解决方法:package结点添加属性 namespace="/"

 

   7.jsp页面上用流的方式输出图片,出现

    getOutputStream() has already been called for this response异常

       解决方法:

            在流输出后加入以下两行代码:

 

 

out.clear();

out = pageContext.pushBody();

 

 

 ②.Spring (做其他DEMO单元测试时问题)

    1.org.springframework.orm.hibernate3.HibernateSystemException: Unknown entity

      原因:在配置文件中没有找到对于的PO对象,加入类似于如下代码即可:

 

<!-- 我记得以前指定名字叫packagesToScan就可的,现在要指定annotatedClasses -->

<property name="annotatedClasses">

<list>

<value>com.shine.jpbm4.po.WfBusiness</value>

<value>com.shine.jpbm4.po.WfStep</value>

<value>com.shine.jpbm4.po.WorkflowBusiInfo</value>

</list>

</property>

    2.使用Springbean属性拷贝工具类,不允许名字一样,而类型却不一样

 

 

 ③.Jbpm4.3 部分

    1.TaskService进行completeTask(taskId,variables)时出现

    No unnamed transitions were found for the task for 'XXX'错误.

      原因JPDL文件定义中,每个transition都有指定对应的名字,如果指定了名字,在进行completeTask时必须指定transtion名字,其实也不 一定是transtion的名字,还有可能是其他类型结点的名字,我们统称为outCome

      解决方法:使用completeTask(taskId,outCome,vauables)方式进行提交任务。

   

    2.对上面的补充,可通过TaskService获取指定taskId的所有outComes

   方:taskService.getOutcomes(taskId);

 

    3.org.hibernate.HibernateException: instance not of expected entity type

        原因进行变量的传输的时候,实体要序列化,实体内部包含的实体也都必须序列化,即实现Serializable接口

   

    4.Jbpm乱码问题:

       当提交的表单POST方式提交的时候,遇到的乱码问题,因为JPDL.XML文件指定的是UTF-8编码,但是Tomcat处理提交数据默认是使用ISO-8859-1,因此需要设置提交requet的编码,以前都使用过滤器进行的,为了简单起见,直接指定requestUTF-8编码格式,request.setCharacterEncoding("UTF-8")

Jbpm4.3和Tomcat6.0兼容问题

最近在研究,想自己随便搞个请假流程,环境是Jbpm4.3 Tomcat6.0,出师不利,刚启动Tomcat就报如下错误:

javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/index_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature

百度之得原因:

原来Jbpm4.3 下的juel.jar, juel-engine.jar, juel-impl.jar包和Tomcat6.0中的el-api.jar包冲突了。

解决方法如下:

 1.将juel.jar, juel-engine.jar, juel-impl.jar拷贝到Tomcat6.0 的lib目录下

2.删除Tomat6.0中lib下的el-api.jar

3.要把项目中的juel.jar, juel-engine.jar, juel-impl.jar包去掉

OK~~再测试成功~~

Eclipse下安装GPD插件的方法

GPD(Graphical Process Designer )图形化流程定义,是一个插件,可安装与Eclipse中,用户可视化的开发流程定义的文件(*.jpdl.xml),其实就是编辑xml文件而已,只是他这个插件符合JPDL的规范,就类似于MyEclipse中的可以对Struts的配置文件进行可视化编辑一样。现在来讲讲安装GPD插件的具体步骤:

1.下载jpbm-4.3.zip 下载地址:sourceforge.net/projects/jbpm/files/

2.在Eclipse中 [ Help ]>> [ install new software ] 在弹出框中选择 [ add ] 按钮 在弹出的小框框中选择 [ Archive.. ] 按钮 添加刚才下载好的东西 :选择{jbpm_home}/install/src/gpd/jbpm-gpd-site.zip 在出现的组件中全选然后一路next直到finish即可,如图:

 

Log4e插件安装和使用

偶发发现这一个东东,Log4e是一个插件,是log4j日志很好的一个编写助手,Log4e是一个免费的Eclipse插件,它可帮助你在你的Java工程中快速加入日志。而且Log4e可以帮助你把System.out.println转成日志的输出,非常方便,还可以瞬间移除代码中的日志代码,无需我们一个一个找到然后再删除

Log4e的插件的下载地址:log4e.jayefem.de/content/view/3/1/

下载然后解压放在MyEclipse的安装目录的dropins文件夹下,然后重启MyEclipse即可。

然后在编写代码工作区,右键便有个Log4e的选项,如图:

JBoss下的log4j 配置

搞了一个上午~~终于在Jboss下成功的将想要的信息写到文件里去了~~

贴个相关配置以及解释~~

<!-- ###
		### 输出方式是 文件 的形式输出 DailyRollingFileAppender 是每天一个文件 
		### 拓展:log4j输出方式有5种,分别是:
		###	1.org.apache.log4j.ConsoleAppender(控制台)
		### 2.org.apache.log4j.FileAppender(文件)
		### 3.org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
		### 4.org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
		### 5.org.apache.log4j.RollingFileAppender(每次都产生一个日志文件)
		### -->
   <appender name="FileRequest" class="org.jboss.logging.appender.DailyRollingFileAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>

	  <!-- ### 指定文件的路径 -->
      <param name="File" value="${jboss.server.log.dir}/sendRequest.log"/>

	  <!-- ### 在重启服务时,设置是否往原有记录继续添加.
	       ### true:继续添加 false:删除掉原来的再添加 -->
      <param name="Append" value="false"/>

	  <!-- ### 类似于过滤器,把低于指定日志级别的日志不显示出来
	       ### 日志级别从高到低:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL -->
	  <param name="Threshold" value="DEBUG"/>  

	  <!-- Rollover at midnight each day -->
      <param name="DatePattern" value="'.'yyyy-MM-dd"/>   

	  <!-- ### 配置日志的输出格式
		   ###%m 输出代码中指定的消息
		   ###%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
		   ###%r 输出自应用启动到输出该log信息耗费的毫秒数
		   ###%c 输出所属的类目,通常就是所在类的全名
		   ###%t 输出产生该日志事件的线程名
		   ###%n 输出一个回车换行符
		   ###%d 输出日志时间点的日期或时间{yyyy-MM-dd HH:mm:ss,SSS}
	       ###%l 输出日志事件的发生位置,包括类目名|发生线程|在代码中的行数 -->
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d{HH:mm:ss} %m%n"/>
      </layout>
   </appender>


   <!-- ### 定义日志名
        ### additivity 是设置是否继承标志父类输出源的标志
		### true:会在父输出源中输出 false:只会在自己定义的输出源输出-->
   <category name="com.shine.proxy.SendRequest" additivity="false">
        <!-- ###定义输出级别 -->
        <priority value="DEBUG" />
		<!-- ###定义引用的Appender -->
		<appender-ref ref="FileRequest"/>
   </category>

   <!--
     ### 对于上一段,还可以有如下写法:
		 <logger name="com.shine.proxy.SendRequest" additivity="false">
			<level value="DEBUG" />
			<appender-ref ref="FileRequest"/>
		 </logger>
     -->

MyEclipse 代码没有提示 解决办法

囧~~~突然间就不行了~~就不能用了~~

百度之得解:

【window】>>【Preferences】>>【Java】>>【Editor】>>【Content Assist】>>【Advanced 】
上面的选项卡(Select the proposal kinds contained in the 'default' content assist list:)

中把 Type Java Proposals 选项打上勾就可以了。

如图: