2007年3月21日
再shortcut 的target 后面加上-data workspace path
如"D:\Program Files\IBM\Rational\SDP\6.0\rationalsdp.exe" -data E:\EE-workspace\1600
posted @
2007-09-13 10:55 sunny 阅读(228) |
评论 (0) |
编辑 收藏
实际编程时,要使Log4j真正在系统中运行事先还要对配置文件进行定义。定义步骤就是对Logger、Appender及Layout的分别使用。
Log4j支持两种配置文件格式,一种是XML格式的文件,一种是java properties(key=value)【Java特性文件(键=值)】。下面我们介绍使用Java特性文件做为配置文件的方法
具体如下:
1、配置根Logger,其语法为:
log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
level : 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
appenderName:就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。
例如:log4j.rootLogger=info,A1,B2,C3
2、配置日志信息输出目的地,其语法为:
log4j.appender.appenderName = fully.qualified.name.of.appender.class //
"fully.qualified.name.of.appender.class" 可以指定下面五个目的地中的一个:
1.org.apache.log4j.ConsoleAppender(控制台)
2.org.apache.log4j.FileAppender(文件)
3.org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
4.org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
5.org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
1.ConsoleAppender选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
Target=System.err:默认情况下是:System.out,指定输出控制台
2.FileAppender 选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
3.DailyRollingFileAppender 选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下:
1)'.'yyyy-MM: 每月
2)'.'yyyy-ww: 每周
3)'.'yyyy-MM-dd: 每天
4)'.'yyyy-MM-dd-a: 每天两次
5)'.'yyyy-MM-dd-HH: 每小时
6)'.'yyyy-MM-dd-HH-mm: 每分钟
4.RollingFileAppender 选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数。
实际应用:
log4j.appender.A1=org.apache.log4j.ConsoleAppender //这里指定了日志输出的第一个位置A1是控制台ConsoleAppender
3、配置日志信息的格式,其语法为:
A.log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
"fully.qualified.name.of.layout.class" 可以指定下面4个格式中的一个:
1.org.apache.log4j.HTMLLayout(以HTML表格形式布局),
2.org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
3.org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
4.org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
1.HTMLLayout 选项
LocationInfo=true:默认值是false,输出java文件名称和行号
Title=my app file: 默认值是 Log4J Log Messages.
2.PatternLayout 选项
ConversionPattern=%m%n :指定怎样格式化指定的消息。
3.XMLLayout 选项
LocationInfo=true:默认值是false,输出java文件和行号
实际应用:
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
B. log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
这里需要说明的就是日志信息格式中几个符号所代表的含义:
-X号: X信息输出时左对齐;
%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。
这里上面三个步骤是对前面Log4j组件说明的一个简化;下面给出一个具体配置例子,在程序中可以参照执行:
log4j.rootLogger=INFO,A1,B2
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
根据上面的日志格式,某一个程序的输出结果如下:
0 INFO 2003-06-13 13:23:46968 ClientWithLog4j Client socket: Socket[addr=localhost/127.0.0.1,port=8002,localport=2014]
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server says: 'Java server with log4j, Fri Jun 13 13:23:46 CST 2003'
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j GOOD
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Command 'HELLO' not understood.'
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j HELP
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Vocabulary: HELP QUIT'
16 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j QUIT
4. # 当输出信息于回滚文件时
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender //指定以文件的方式输出日志
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log //文件位置,也可以用变量${java.home}、rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=10KB //文件最大尺寸
log4j.appender.ROLLING_FILE.MaxBackupIndex=1 //备份数
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
××××××××××××××××××××××××××××××××××××××××××××××××
Log4j比较全面的配置
LOG4J的配置之简单使它遍及于越来越多的应用中了:Log4J配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了,
log4j.rootLogger=DEBUG,CONSOLE,A1,im
log4j.addivity.org.apache=true
# 应用于控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n
#应用于文件
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# Use this layout for LogFactor 5 analysis
# 应用于文件回滚
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log //文件位置,也可以用变量${java.home}、rolling.log
log4j.appender.ROLLING_FILE.Append=true //true:添加 false:覆盖
log4j.appender.ROLLING_FILE.MaxFileSize=10KB //文件最大尺寸
log4j.appender.ROLLING_FILE.MaxBackupIndex=1 //备份数
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#应用于socket
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志给邮件
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=web@www.wuset.com
log4j.appender.MAIL.SMTPHost=www.wusetu.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=web@www.wusetu.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# 用于数据库
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
#自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
posted @
2007-06-05 19:37 sunny 阅读(485) |
评论 (1) |
编辑 收藏
<%@page contentType="text/html;charset=gbk" %>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<h3 align="center">Dispatch Action</h3>
<hr>
<pre>
根据请求中的某个(1)参数的值来调用Action的方法(2)。
(1)参数名字在<action parameter="method" />
(2)方法名字为 method 参数的值。
</pre>
<center>
<a href="${pageContext.request.contextPath}/dispatch.do?method=login">login</a>
<a href="${pageContext.request.contextPath}/dispatch.do?method=find">find</a>
<a href="${pageContext.request.contextPath}/dispatch.do?method=findById">findById</a>
<a href="${pageContext.request.contextPath}/dispatch.do?method=register">register</a>
<a href="${pageContext.request.contextPath}/dispatch.do?method=remove">remove</a>
<a href="${pageContext.request.contextPath}/dispatch.do?method=modify">modify</a>
</center>
<hr>
<h3 align="center">LookupDispatch Action</h3>
<hr>
<pre>
</pre>
<center>
<form method="post" action="${pageContext.request.contextPath}/lookup.do">
<input type="submit" value="<bean:message key="submit.login"/>" name="method">
<input type="submit" value="<bean:message key="submit.find"/>" name="method">
<input type="submit" value="<bean:message key="submit.findById"/>" name="method">
<input type="submit" value="<bean:message key="submit.register"/>" name="method">
<input type="submit" value="<bean:message key="submit.remove"/>" name="method">
<input type="submit" value="<bean:message key="submit.modify"/>" name="method">
</form>
</center>
<!--
<h3 align="center">LookupDispatch Action</h3>
<hr>
<pre>
</pre>
<center>
<form method="post" action="${pageContext.request.contextPath}/lookup.do">
<input type="hidden" name="method" value="login">
<input type="submit" value="login" name="m" onclick="this.form.method.value='login'">
<input type="submit" value="find" name="m" onclick="this.form.method.value='find'">
<input type="submit" value="findById" name="m" onclick="this.form.method.value='findById'">
<input type="submit" value="register" name="m" onclick="this.form.method.value='register'">
<input type="submit" value="remove" name="m" onclick="this.form.method.value='remove'">
<input type="submit" value="modify" name="m" onclick="this.form.method.value='modify'">
</form>
</center>
-->
<hr>
<h3 align="center">MappingDispatch Action</h3>
<hr>
<pre>
根据<action>标记的parameter属性的值来调用Action的方法(1)。
(1)方法名字为 parameter属性的值。
</pre>
<center>
<a href="${pageContext.request.contextPath}/mapping/login.do">login</a>
<a href="${pageContext.request.contextPath}/mapping/find.do">find</a>
<a href="${pageContext.request.contextPath}/mapping/findById.do?id=1">findById</a>
<a href="${pageContext.request.contextPath}/mapping/register.do">register</a>
<a href="${pageContext.request.contextPath}/mapping/remove.do?id=2">remove</a>
<a href="${pageContext.request.contextPath}/mapping/modify.do">modify</a>
</center>
=====================================================
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="loginForm" type="com.allanlxf.action.LoginForm"/>
<form-bean name="userForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="userName" type="java.lang.String" />
<form-property name="password" type="java.lang.String" />
</form-bean>
</form-beans>
<action-mappings>
<action path="/core/login" type="com.allanlxf.action.LoginAction"
name="loginForm" input="/core/login.jsp" validate="true" scope="request">
<exception key="errors.root"
path="/core/error.jsp"
type="com.allanlxf.biz.IllegalUserException" />
<forward name="success" path="/core/success.jsp" redirect="true"/>
<forward name="fail" path="/core/fail.jsp" />
</action>
<action path="/dispatch" type="com.allanlxf.struts.actions.UserAction" parameter="method">
<forward name="login" path="/actions/pages/login_next.jsp" />
<forward name="find" path="/actions/pages/find_next.jsp" />
<forward name="findById" path="/actions/pages/findById_next.jsp" />
<forward name="remove" path="/actions/pages/remove_next.jsp" />
<forward name="modify" path="/actions/pages/modify_next.jsp" />
<forward name="register" path="/actions/pages/register_next.jsp" />
</action>
<action path="/mapping/login" type="com.allanlxf.struts.actions.UserMappingAction" parameter="login">
<forward name="next" path="/actions/pages/login_next.jsp" />
</action>
<action path="/mapping/find" type="com.allanlxf.struts.actions.UserMappingAction" parameter="find">
<forward name="next" path="/actions/pages/find_next.jsp" />
</action>
<action path="/mapping/findById" type="com.allanlxf.struts.actions.UserMappingAction" parameter="findById">
<forward name="next" path="/actions/pages/findById_next.jsp" />
</action>
<action path="/mapping/remove" type="com.allanlxf.struts.actions.UserMappingAction" parameter="remove">
<forward name="next" path="/actions/pages/remove_next.jsp" />
</action>
<action path="/mapping/modify" type="com.allanlxf.struts.actions.UserMappingAction" parameter="modify">
<forward name="next" path="/actions/pages/modify_next.jsp" />
</action>
<action path="/mapping/register" type="com.allanlxf.struts.actions.UserMappingAction" parameter="register">
<forward name="next" path="/actions/pages/register_next.jsp" />
</action>
<action path="/lookup" type="com.allanlxf.struts.actions.UserLookupAction" parameter="method">
<forward name="login" path="/actions/pages/login_next.jsp" />
<forward name="find" path="/actions/pages/find_next.jsp" />
<forward name="findById" path="/actions/pages/findById_next.jsp" />
<forward name="remove" path="/actions/pages/remove_next.jsp" />
<forward name="modify" path="/actions/pages/modify_next.jsp" />
<forward name="register" path="/actions/pages/register_next.jsp" />
</action>
<action path="/dyna/register" type="com.allanlxf.action.RegisterAction"
name="userForm">
<forward name="success" path="/dyna/success.jsp"/>
</action>
</action-mappings>
<message-resources parameter="com.allanlxf.MessageResources" />
</struts-config>
posted @
2007-04-25 16:12 sunny 阅读(652) |
评论 (0) |
编辑 收藏
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public abstract class HttpFilter implements Filter
{
private FilterConfig config;
//////////////////////////////////
public void init(FilterConfig config) throws ServletException
{
this.config = config;
init();
}
public void init() throws ServletException
{
}
///////////////////////////////
public FilterConfig getFilterConfig()
{
return config;
}
public String getInitParameter(String name)
{
return config.getInitParameter(name);
}
public ServletContext getServletContext()
{
return config.getServletContext();
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
doFilter((HttpServletRequest)request, (HttpServletResponse)response, chain);
}
public abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException;
public void destroy()
{
}
}
posted @
2007-04-06 16:31 sunny 阅读(299) |
评论 (0) |
编辑 收藏
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
public class ConnectionFactory
{
/**
oracle 分页
select * from (
select a.*, ROWNUM rn from ( select * from user_info ) a
where ROWNUM<=40 )
where rn >=21
*/
private static Properties config = new Properties();
static
{
try
{
InputStream in = ConnectionFactory.class.getClassLoader().getResourceAsStream("dbconfig.properties");
config.load(in);
in.close();
}catch(IOException e)
{
e.printStackTrace();
throw new ExceptionInInitializerError(e.getMessage());
}
}
public static Connection getConnection()
{
if(config.getProperty("jndi-name") != null)
{
return getJndiConnection();
}
return getDirectConnection();
}
public static Connection getJndiConnection()
{
Connection con = null;
try
{
/**context.xml
数据源的配置
<Context>
<Resource name="jdbc/oracle" auth="Container" type="javax.sql.DataSource" maxActive="2" maxIdle="1" maxWait="-1"
username="openlab" password="open123" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@192.168.0.20:1521:tarena"/>
</Context
*/
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/" + config.getProperty("jndi-name"));
con = ds.getConnection();
}catch(Exception e)
{
e.printStackTrace();
}
return con;
}
public static Connection getDirectConnection()
{
Connection con = null;
try
{
Class.forName(config.getProperty("driver"));
con = DriverManager.getConnection(config.getProperty("dburl") ,config.getProperty("user"), config.getProperty("password"));
}catch(ClassNotFoundException cne)
{
cne.printStackTrace();
}catch(SQLException sqle)
{
sqle.printStackTrace();
}
return con;
}
public static void close(ResultSet rs, Statement st, Connection con)
{
try
{
rs.close();
}catch(Exception e)
{
}
try
{
st.close();
}catch(Exception e)
{
}
try
{
con.close();
}catch(Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Connection con = ConnectionFactory.getConnection();
System.out.println(con);
con.close();
}
}
posted @
2007-04-05 15:30 sunny 阅读(149) |
评论 (0) |
编辑 收藏
上午:
一.JDBC原理概述
1,JDBC是一套协议,是JAVA开发人员和数据库厂商达成的协议,也就是由Sun定义一组接口,由数据库厂商来实现,并规定了JAVA开发人员访问数据库所使用的方法的调用规范。
2,JDBC的实现是由数据库厂商提供,以驱动程序形式提供。
3,JDBC在使用前要先加载驱动。
JDBC对于使用者要有一致性,对不同的数据库其使用方法都是相同的。
驱动开发必须要实现Driver接口。
数据库驱动的实现方式
JDBC-ODBC桥接式
JDBC网络驱动,这种方式是通过中间服务器的协议转换来实现的
JDBC+本地驱动,这种方式的安全性比较差。
JDBC驱动,由数据库厂商实现。
二.JDBC的API
java.sql包和javax.sql包
Driver接口(驱动),在加载某一 Driver 类时,它应该创建自己的实例并向 DriverManager 注册该实例。这意味着用户可以通过调用以下程序加载和注册一个驱动程序
Class.forName("oracle.jdbc.driver.OracleDriver")
DriverManager类(驱动管理器),它可以创建连接,它本身就是一个创建Connection的工厂(Factory)。
Connection接口,会根据不同的驱动产生不同的连接
Statement接口,发送sql语句
ResultSet接口(结果集),是用来接收select语句返回的查询结果的。其实质类似于集合。
下午:
三.JDBC应用步骤
1,注册加载一个driver驱动
2,创建数据库连接(Connection)
3,创建一个Statement(发送sql)
4,执行sql语句
5,处理sql结果(select语句)
6,关闭Statement
7,关闭连接Connection。
注意:6,7两个步骤势必须要做的,因为这些资源是不会自动释放的,必须要自己关闭
访问Oracle的数据库的驱动名字叫ojdbc14.jar,要使用这个驱动程序,要先将他加到环境变量CLASSPATH中。
注册加载驱动driver,也就是强制类加载
Class.forName(Driver包名.Driver类名)。
Driver d=new Driver类();//注意:这个方法不能用参数来构造
DriverManager.registerDriver(d);
Oracle的Driver的全名oracle.jdbc.driver.OracleDriver
mysql的Driver的全名com.mysql.jdbc.Driver
SQLServer的Driver的全名com.microsoft.jdbc.sqlserver.SQLServerDriver
创建连接
DriverManager.getConnection(String url,String username,String password);
Connection连接是通过DriverManager的静态方法getConnection(.....)来得到的,这个方法的实质是把参数传到实际的Driver中的connect()方法中来获得数据库连接的。
Oracle的URL值是由连接数据库的协议和数据库的IP地址及端口号还有要连接的数据库的库名(DatebaseName)
Oracle URL的格式
jdbc:oracle:thin:(协议)@XXX.XXX.X.XXX:XXXX(IP地址及端口号):XXXXXXX(所使用的库名)
例:jdbc:oracle:thin:@192.168.0.20:1521:tarenadb
MySql URL的写法
例: jdbc:mysql://localhost:3306/tarena
SQLServer URL的写法
例:jdbc:microsoft:sqlserver://localhost:1433/test
java -Djdbc.drivers=驱动的完整类名
使用虚拟机参数,加载驱动 -D表示为虚拟机参数赋值
java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver:com.mysql.jdbc.Driver
四.JDBC基本方法
DriverManager:如果有多个驱动可用的话,DriverManager会选择其中一个.
Driver:可以选择固定的驱动
Driver driver = new oracle.jdbc.driver.OracleDriver();
String user = "sd0613";
String password = "sd0613";
Properties prop = new Properties();
prop.setProperty("user",user);
prop.setProperty("password",password);
driver.connect(url,properties);
executeQuery(sqlString);//返回结果集
executeUpdate(sqlString);//返回值为该次操作影响的记录条数,create table返回0
execute(sqlString);
//适用于不知道具体的操作是什么,返回值是boolean类型的
//如果返回值是true,代表执行查询操作;否则代表执行更新操作.
ResultSet
next()方法:
1.判断是否存在下一条记录
2.将游标移向下一条记录
getXXX(字段名或字段序号)//注意:字段序号从1开始
关闭问题:
使用Connection对象获得一个Statement,Statement中的executeQuery(String sql) 方法可以使用select语句查询,并且返回一个结果集 ResultSet通过遍历这个结果集,可以获得select语句的查询结果,ResultSet的next()方法会操作一个游标从第一条记录的前边开始读取,直到最后一条记录。executeUpdate(String sql) 方法用于执行DDL和DML语句,可以update,delete操作。
注意:要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为Statement和ResultSet是需要连接时才可以使用的,所以在使用结束之后有可能其他的Statement还需要连接,所以不能先关闭Connection。
1.回忆下昨天的一些JDBC的配置
(1) 驱动:
ojdbc14.jar (Oracle)
mysql-connector-java-3.1.11-bin.jar(MySql)
(2) 实现了Driver接口的驱动类(程序中要加载的类):
jdbc.oracle.driver.OracleDriver (Oracle)
com.mysql.jdbc.Driver (MySql)
(3)连接数据库的URL
jdbc:oracle:thin:@192.168.0.24:1521:tarena (Oracle)
jdbc:mysql://192.168.0.24:3306/test (MySql)
2.PreparedStatement概述
SQL语句传到数据库后,数据库会先对其编译再执行。在使用Statement时,如果要执行一组类似的SQL操作时,这样做效率很低,而且把不同类型的数据直接写在SQL语句中是比较麻烦的。这时应该用PreparedStatement来代替Statement,PreparedStatement 接口继承 Statement,并和他在两方面有所不同:
(1)PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句先“准备好”。包含于 PreparedStatement对象中的SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。
(2)由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。
作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 IN 参数占位符的值。同时,三种方法 execute()、 executeQuery() 和 executeUpdate() 已被更改以使之不再需要参数。这些方法的 Statement 形式(接受 SQL 语句参数的形式)不应该用于 PreparedStatement 对象。
3.创建 PreparedStatement 对象
以下的代码段(其中 con 是 Connection 对象)创建包含带两个 IN 参数占位符的 SQL 语句的 PreparedStatement 对象:
PreparedStatement pstmt = con.prepareStatement("UPDATE table4 SET m = ? WHERE x = ?");
pstmt 对象包含语句 "UPDATE table4 SET m = ? WHERE x = ?",它已发送给DBMS,并编译好为执行作好了准备。
4.传递 IN 参数
在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有Java 类型 long,则使用的方法就是 setLong。setXXX 方法的第一个参数是要设置的参数的序数位置(从1开始),第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为 123456789,第二个参数设为 100000000:
pstmt.setLong(1, 123456789);
pstmt.setLong(2, 100000000);
5.ResultSetMetaData
元数据是用来描述数据的数据,ResultSetMetaData就是来描述结果集的列的类型和属性信息,比如可以通过它得到结果集的列数,列名等。具体可在API中查阅java.sql.ResultSetMetaData。
ResultSetMetaData对象可以通过ResultSet对象的getMetaData()来得到。
ResultSetMetaData对象有以下三个方法比较常用:
getColumnCount():获得实际列数
getColumnName(int colnum):获得指定列的列名
getColumnType(int colnum):获得指定列的数据类型(Types里面的类型,存放的是整数)
6.JDBC是持久层的技术,是JAVA连接数据库目前最通用的手段。其他的持久层技术,比如接下来我们要学的Hibernate,底层也是由JDBC实现的。持久层是与业务无关的,具体的业务由业务层完成,当业务层需要和数据库进行交互时,就需要通过持久层来操作。
7.BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
由于System.in是字节流,我们需要把他转成字符流。并用BufferedReader包装后方便我们的操作。
8.为了区分表中不同的数据,我们要给放入表中持久化的每个对象都加上一个唯一的标识,这就是ID,ID是与业务无关的。ID的生成方法有很多,在Oracle数据库中我们一半利用Sequence来生成。
9.读取配置文件时,我们采用Properties对象。它是HashTable的子类,它有个load(InputStream inStream) 的方法可以直接从输入流中读取属性列表(键值对)。getProperty(String key) 方法用指定的键在此属性列表中搜索值。
1.Registering a driver
2.Establishing a connection to the datebase
3.Creating a statement
4.Executing a SQL
5.Processing the results
6.Closing down JDBC objects
JDBC第三天
上午:
一.事务(Transaction)
原子操作:不可再分的操作,一个操作不能再分成比它更细小的操作.
事务是针对原子操作的,要求原子操作不可再分,并且必须同时成功同时失败。
事务就是把一些非原子操作,变成原子操作,由应用服务器来提出要求,由数据库服务器来执行操作.
在JDBC中默认是自动提交的,如果要想使用事务,需要按以下步骤执行:
1.要调用con.setAutoCommite(false)方法(打开事务边界),把自动提交(commit)置为false。
2.进行正常的数据库操作
3.如果操作成功了可以选择con.commit(),或者操作失败时选择con.roolback()------
(回滚:数据恢复到之前的情况)
注意:打开事务就要关闭自动提交,当不需要再使用事务的时候调用
setAutoCommite(true).
事务性资源(监控完整性)
二.事务并发产生的问题
三种并发产生的后果:
1,脏读:一个事务读取到了另外一个事务没有提交的数据。(Dirty Read)
2,重复读:一个事务读取到了另外一个事务提交的数据。它是要保持在同一时间点上读取到的数据相同,希望在一段时间内的数据是不变的。
3,幻读:一个事务读取到了另外一个事务提交的数据。用同样的操作读取两次,得到的记录数不相同。
三.事务隔离级别
五种控制级别:
TRANSACTION_NONE不使用事务。
TRANSACTION_READ_UNCOMMITTED 允许脏读。
TRANSACTION_READ_COMMITTED防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别----------------------
TRANSACTION_REPEATABLE_READ可以防止脏读和不可重复读,
TRANSACTION_SERIALIZABLE可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率
以上的五个事务隔离级别都是在Connection类中定义的静态常量,使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
如:con.setTransactionIsolation(Connection.REPEATABLE_READ);
下午:
四.JDBC2.0新特性
1.可滚动特性和可更新特性
JDBC1.0中是指游标的移动的方向和方式是单向,单步(相对)移动,功能比较简单.
JDBC2.0中游标可以双向,相对或者绝对移动.
可滚动结果集:这种结果集不但可以双向滚动,相对定位,绝对定位,并且还可以修改数据信息。
1)滚动特性
定位函数:aaa
boolean absolute(int row),定位到指定的记录位置。定位成功返回true,不成功返回false。
void afterLast() ,把游标移动到最后一条记录的后面(逻辑位置)。 一定会有的
void beforeFirst() ,把游标移动到第一条记录的前面(逻辑位置)。
//由于第一条记录的前面和最后一条记录的后面这两个位置肯定存在,所以无需判断是否存在,返回值设为void.
boolean first(),把游标定位到第一条记录,相对定位;
boolean last(),把游标定位到最后一条记录 也是相对的概念。
//当结果集为空的时候,这两个方法会返回false.
boolean next(),此方法是使游标向下一条记录移动。
boolean previous() ,此方法可以使游标向上一条记录移动,前提是前面还有记录。
boolean relative(int rows) ,相对定位方法,参数值可正可负,参数为正,游标从当前位置向后移动指定值条记录,参数为负,游标从当前位置向前移动指定值条记录。
判断函数:
ifBeforeFirst()判断是否在在第一条记录之前.
ifAfterLast()判断是否在在最后一条记录之后.
ifFirst()判断是否为第一条记录.
ifLast()判断是否为最后一条记录.
要使用可滚动结果集时,需要一次设置更新特性与滚动特性,不能分开.
1.更新特性常量:
CONCUR_READ_ONLY 只读结果集 (默认的)
CONCUR_UPDATABLE 可更新结果集
2.滚动特性常量:
TYPE_FORWARD_ONLY ,该常量表示指针只能向前移动的 ResultSet 对象的类型。(默认)
双向滚动:
不敏感:TYPE_SCROLL_INSENSITIVE ,该常量指示可滚动但通常不受其他更改影响的 ResultSet 对象的类型。
敏感的:TYPE_SCROLL_SENSITIVE ,该常量指示可滚动并且通常受其他更改影响的 ResultSet 对象的类型。
//敏感:数据库改变,结果集改变.
语法:
Statement st=null;
st=con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_UPDATABLE)
在创建Statement的时候就要指定这两个参数,使用Statement,第一个参数代表滚动特性常量,第二个代表更新特性常量
----------------------------------------
2)可更新特性
a.moveToInsertRow();记录当前游标位置,将游标移到和结果集结构类似的缓冲区;
b.使用updateXxx(int column,columnType value)方法来更新指定列数据;
c.使用insertRow() 方法插入记录,加信结果集,更新
d.将游标指回原位,moveToCurrentRow() 。
2,3步,可循环
-----------------------------------------------------
能否使用JDBC2.0 ResultSet的新特性,要看使用的数据库驱动是否支持.
还有只能用于单表且表中有主键字段(可能会是联合主键),不能够有表连接,会取
可更新操作必须满足以下条件:
a.查询只能引用一张表.
b.不能包含任何连接操作.
c.必须把完整的主键查到结果集里面;
d.保证所有字段为非空字段并且没有默认值。
五.数据库元数据:
DatabaseMetaData dbmd = con.getMetaData();//得到数据库元数据
dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);//判断是否支持可更新操作
六.批量更新
优势:
1.节省传递时间
2.并发处理
PreparedStatement:
1.addBatch() 将一组参数添加到 PreparedStatement对象内部
2.executeBatch() 将一批参数提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。
Statement:
addBatch(String sql)方法会在批处理缓存中加入一条sql语句
executeBatch()执行批处理缓存中的所有sql语句。
注意:PreparedStatement中使用批量更新时,要先设置好参数后再使用addBatch()方法加入缓存。
批量更新中只能使用更新或插入语句
//
Statement stm=con.createStatement(int resultSetType,int resultSetConcurrency);创建的时候就要指明要什么样的结果集。
先可滚,后可更新
boolean absolute (int row)绝对定位,
afterLast()定位到最后一条记录的后面