日期:2014-05-16  浏览次数:20467 次

使用oracle数据库的J2EE项目经验总结
总结了一下,这两天开发中的觉得有用的东西

1. Oracle中的sequence

我有两个表,一个是物资表,其主键是数据库自增序列,另一个表是物资明细表,其主键也是自增序列,物资表的主键是此表的外键。现在我有一个插入的操作,需要现在物资表里插入一条数据(id插入使用s_id.nextval,s_id表示序列),然后在物资明细表中也对应的插入数据。然后,问题产生了,当我需要插入物资明细表的时候由于不知道物资表的id是多少,导致没法进行操作。据了解,如果使用了hibernate的话,能够直接配置好了拿到此id,可是我们的项目只用了struts+sping。

别人给的解决方案:

(1) 将这两个表的操作放到一个事务中去做,物资表插入完之后,直接查找该表拿到最后一个插入的id进行操作。

(2) 使用s_id的nextval和currval操作,由于每次使用currval的时候必须是先进行过nextval操作,如果插入之后使用查询currval取值,这样取到的值肯定是正确的,不用考虑是否有别人同时也对此表进行操作,导致取出的值不一样,这个方法我尝试了,但由于在一个方法中要两次执行sql语句,觉得太麻烦。

(3) 最后我才明白了sequence是怎么回事,在数据库中sequences和表是独立的,如果在设计数据库表的时候,比如id字段不让它绑定序列值,这样序列就是自己增加,和id没关系。所以解决方法就是,在插入数据库表的时候首先使用sql语句:

"select s_id.nextval from dual"拿到唯一的id,然后使用这个id进行插入操作。以前很纠结是因为总以为只要没有插入操作,nextval是从数据库表中具体数据的下一条开始的,真是无知啊。

2. Oracle中的dual表是什么东西

因为发现在数据库中没有存在dual表,却可以进行操作,原来dual是oracle数据库的虚表,是Oracle与数据字典一起自动创建的一个表,只有一行一列,返回值只有一条数据,即使进行的是多条数据的操作,这样像调用系统时间select to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss') from dual之类的都可以使用,真是简便。

3. 在J2EE项目中对数据库中的BLOB类型数据的读取

(1)sping中的配置
<bean id="defaultLobHandler"
?? class="org.springframework.jdbc.support.lob.DefaultLobHandler"
?? lazy-init="true" />


(2) 在DAOImpl中添加资源及对应的setter getter
  @Resource
   private LobHandler lobHandler;

(3)  对于插入数据库方法add(),使用jdbcTemplate的时候请使用lobCreator,例子如下:
jdbcTemplate.execute(sql,new AbstractLobCreatingPreparedStatementCallback(this.lobHandler)  
   { protected void setValues(PreparedStatement ps,LobCreator lobCreator) 
          throws SQLException 
     {
	  ps.setString(1, bean.getDeviationReportNumber());
	  ps.setString(2, bean.getMaterialsName());
	  lobCreator.setBlobAsBytes(ps, 3, bean.getDeviationReportAttachment());
						
     }
					
   });

(4)  对于读取数据库方法,使用jdbcTemplate时请使用lobHandler.getBlobAsBytes,例子如下:
jdbcTemplate.query(sql, new AbstractLobStreamingResultSetExtractor() {
	protected void streamData(ResultSet rs) throws SQLException,IOException 
		{
			reportBean.setId(rs.getLong("ID"));				
			reportBean.setDeviationReportAttachment(lobHandler
						.getBlobAsBytes(rs, 9));
			}
		}, params);

4.InputStream与byte[]转换
private byte[] InputStreamToByte(InputStream is) throws IOException {
   ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
   int ch;
   while ((ch = is.read()) != -1) {
    bytestream.write(ch);
   }
   byte imgdata[] = bytestream.toByteArray();
   bytestream.close();
   return imgdata;
  }


5.使用struts2实现文件上传与下载

(1)文件的上传是在jsp页面中使用<s:file />即可生成一个“浏览”按钮,在写一个 在action中对文件进行处理。
(2)文件下载
在struts.xml中配置如下:
<action name="download" class="com.cnpc.action.MaterialReceiveAction" >
			<result name="success" type="stream">
				<param name="contentType">application/msword</param>
				<param name="inputName">inputStream</param>
				<param name="contentDisposition">attachment;filename="${exportFilename}"</param>
				<param name="bufferSize">4096</param>
			</result>
		</action>	

在action中写:
/**
	 * 获取下载文件名 中文名
	 * @return
	 */
	public String getExportFilename() 
	{
		try {
			return new String(this.exportFilename.getBytes(), "ISO8859-1");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return "default";
		}
	}
	public void setExportFilename(String exportFilename) {
		this.exportFilename = exportFilename;
	}