相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半

自动化”的ORM实现。

以前ORM的框架(hibernate,ojb)的局限:

1. 系统的部分或全部数据来自现有数据库,处于安全考虑,只对开发团队提供几条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。

2. 开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由存储过程实现(就笔者工作所面向的金融行业而言,工商银行、中国银行、交通银行,都在开发规范中严格指定)

3. 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。

ibatis 的着力点:

在于POJO 与SQL之间的映射关系。也就是说,ibatis

并不会为程序员在运行期自动生成SQL 执行。具体的SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。

Ibatis与Hibernate的区别:

Hibernate提供了全面的数据库封装机制的“全自动化”ORM 实现而言,“全自动”ORM 实现了POJO 和数据库表之间的映射,以及SQL 的自动生成和执行,而ibatis 的着力点,则在于POJO 与SQL之间的映射关系。也就是说,ibatis并不会为程序员在运行期自动生成SQL 执行。具体的SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。

ibatis配置文件:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings ⑴

cacheModelsEnabled="true"

enhancementEnabled="true"

lazyLoadingEnabled="true"

errorTracingEnabled="true"

maxRequests="32"

maxSessions="10"

maxTransactions="5"

useStatementNamespaces="false"

/>

<transactionManager type="JDBC"> ⑵

<dataSource type="SIMPLE"> ⑶

<property name="JDBC.Driver"

value="com.p6spy.engine.spy.P6SpyDriver"/>

<property name="JDBC.ConnectionURL"

value="jdbc:mysql://localhost/sample"/>

<property name="JDBC.Username" value="user"/>

<property name="JDBC.Password" value="mypass"/>

<property name="Pool.MaximumActiveConnections"

value="10"/>

<property name="Pool.MaximumIdleConnections" value="5"/>

<property name="Pool.MaximumCheckoutTime"

value="120000"/>

<property name="Pool.TimeToWait" value="500"/>

<property name="Pool.PingQuery" value="select 1 from

ACCOUNT"/>

<property name="Pool.PingEnabled" value="false"/>

<property name="Pool.PingConnectionsOlderThan"

value="1"/>

<property name="Pool.PingConnectionsNotUsedFor"

value="1"/>

</dataSource>

</transactionManager>

<sqlMap resource="com/ibatis/sample/User.xml"/> ⑷

<sqlMap resource="com/ibatis/sample/Address.xml"/>

</sqlMapConfig>

⑴Settings 节点 参数

描述

cacheModelsEnabled

是否启用SqlMapClient上的缓存机制。建议设为"true"

enhancementEnabled

是否针对POJO启用字节码增强机制以提升getter/setter的调用效能,避免使用JavaReflect所带来的性能开销。同时,这也为Lazy Loading带来了极大的性能提升。建议设为"true"

errorTracingEnabled

是否启用错误日志,在开发期间建议设为"true"以方便调试

lazyLoadingEnabled

是否启用延迟加载机制,建议设为"true"

maxRequests

最大并发请求数(Statement并发数)

maxTransactions

最大并发事务数

maxSessions

最大Session 数。即当前最大允许的并发SqlMapClient数。maxSessions设定必须介于maxTransactions和maxRequests之间,即 maxTransactions<maxSessions=<maxRequests

useStatementNamespaces

是否使用Statement命名空间。这里的命名空间指的是映射文件中,sqlMap节点的namespace属性,如在上例中针对t_user

表的映射文件sqlMap节点:

<sqlMap namespace="User">

这里,指定了此sqlMap节点下定义的操作均从属于"User"命名空间。

在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,如:sqlMap.update("User.updateUser",user);否则直接通过Statement名称调用即可,如:sqlMap.update("updateUser",user);

但请注意此时需要保证所有映射文件中,Statement定义无重名。

⑵ transactionManager节点

transactionManager 节点定义了ibatis 的事务管理器,目前提供了以下几种选择:

Ø JDBC

通过传统JDBC Connection.commit/rollback实现事务支持。

Ø JTA

使用容器提供的JTA服务实现全局事务管理。

Ø EXTERNAL

外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自动的事务管理机制。此时ibatis 将把所有事务委托给外部容器进行管理。此外,通过Spring 等轻量级容器实现事务的配置化管理也是一个不错的选择。关于结合容器实现事务管理,参见“高级特性”中的描述。

⑶ dataSource节点

dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性。

type属性: dataSource节点的type属性指定了dataSource的实现类型。可选项目:

Ø SIMPLE:

SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的数据库连接池机制,对应ibatis 实现类为com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。

Ø DBCP:

基于Apache DBCP 连接池组件实现的DataSource 封装,当无容器提供DataSource 服务时,建议使用该选项,对应ibatis 实现类为com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。

Ø JNDI:

使用J2EE 容器提供的DataSource 实现,DataSource 将通过指定的JNDI Name 从容器中获取。对应ibatis 实现类为com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory。

dataSource的子节点说明(SIMPLE&DBCP):

参数

描述

JDBC.Driver

JDBC 驱动。如:com.microsoft.jdbc.sqlserver.SQLServerDriver

JDBC.ConnectionURL

数据库URL。如:

jdbc:microsoft:sqlserver://localhost:1433;databaseName=ibatis如果用的是SQLServer JDBC Driver,需要在url后追加SelectMethod=Cursor以获得JDBC事务的多Statement支持。

JDBC.Username

数据库用户名

JDBC.Password

数据库用户密码

Pool.MaximumActiveConn

ections

数据库连接池可维持的最大容量。

Pool.MaximumIdleConnec

tions

数据库连接池中允许的挂起(idle)连接数。

以上子节点适用于SIMPLE 和DBCP 模式,分别针对SIMPLE 和DBCP 模式的DataSource私有配置节点如下:

SIMPLE:

Pool.MaximumCheckoutTime

数据库联接池中,连接被某个任务所允许占用的最大时间,如果超过这个时间限定,连接将被强制收回。(毫秒)

Pool.TimeToWait

当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)

Pool.PingQuery

数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。检测语句应该是一个最简化的无逻辑SQL。如“select 1 from t_user”,如果执行此语句成功,连接池管理器将认为此连接处于可用状态

Pool.PingEnabled

是否允许检测连接状态。

Pool.PingConnectionsOlderThan

对持续连接时间超过设定值(毫秒)的连接进行检测。

Pool.PingConnectionsNotUsedFor

对空闲超过设定值(毫秒)的连接进行检测。

DBCP:

Pool.MaximumWait

当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)

Pool.ValidationQuery

数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。检测语句应该是一个最简化的无逻辑SQL。如“select 1 from t_user”,如果执行此语句

成功,连接池管理器将认为此连接处于可用状态。

Pool.LogAbandoned

当数据库连接被废弃时,是否打印日志。

Pool.RemoveAbandonedTimeout

数据库连接被废弃的最大超时时间

Pool.RemoveAbandoned

当连接空闲时间超过RemoveAbandonedTimeout时,是否将其废弃。

JNDI:

由于大部分配置是在应用服务器中进行,因此ibatis中的配置相对简单,下面是分别使用JDBC和JTA事务管理的JDNI配置:

使用JDBC事务管理的JNDI DataSource配置

<transactionManager type="JDBC" >

<dataSource type="JNDI">

<property name="DataSource" value="java:comp/env/jdbc/myDataSource"/>

</dataSource>

</transactionManager>

<transactionManager type="JTA" >

<property name="UserTransaction" value="java:/ctx/con/UserTransaction"/>

<dataSource type="JNDI">

<property name="DataSource" value="java:comp/env/jdbc/myDataSource"/>

</dataSource>

</transactionManager>

⑷ sqlMap节点

sqlMap 节点指定了映射文件的位置,配置中可出现多个sqlMap 节点,以指定项目内所包含的所有映射文件。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap namespace="映射文件名称:User">

<typeAlias alias="user" type="com.ibatis.sample.User"/> 给对应的类取别名

<cacheModel id="userCache" type="LRU">

<flushInterval hours="24"/> 设定缓存有效期

<flushOnExecute statement=" updateUser"/>

指定执行特定Statement时,将缓存清空。如updateUser操作将更新数据库中的用户信息,这将导致缓存中的数据对象与数据库中的实际数据发生偏差,因此必须将缓存清空以避免脏数据的出现。

<property name="size" value="1000" /> CacheModel中最大容纳的数据对象数量

</cacheModel>

申明了一个名为"userCache"的cacheModel,之后可以在Statement申明中对其进行引用:例如:

<select id="getUser" parameterClass="java.lang.String" resultClass="user"

cacheModel="userCache">

<select id="" parameterClass="java.lang.String" resultClass="user">

<![CDATA[    可以避免SQL 中与XML 规范相冲突的字符对XML映射文件的合法性造成影响。

SQL语句

]]>

</select>

< update id=" " parameterClass="java.lang.String" >

<![CDATA[

SQL语句

]]>

</ update >

< insert id=" " parameterClass="java.lang.String" >

<![CDATA[

SQL语句

]]>

</ insert >

< delete id="" parameterClass="java.lang.String" >

<![CDATA[

SQL语句

]]>

</ delete >

</sqlMap>

需要一个JAVABEAN:有getter和setter方法

如何读取配置文件:

       public class SQLMapper {

       public static SqlMapClient sqlMapper;

       static{

              String resource = "org/lzp/xml/SqlMapConfig.xml";指明了配置文件的相对路径

              try {

                     Reader reader = Resources.getResourceAsReader(resource);

           //ibatis2.0

           /* XmlSqlMapClientBuilder xmlBuilder =

new XmlSqlMapClientBuilder();

sqlMapper = xmlBuilder.buildSqlMap(reader);

*/

//ibatis1.0

                     sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

}

SqlMapClient是ibatis运作的核心,所有操作均通过SqlMapClient实例完成。例如:

sqlMapper.insert("名称", 参数);

sqlMapper提供了众多数据操作方法,下面是一些常用方法的示例,具体说明文档请参见ibatis java doc,或者ibatis官方开发手册。

Statement配置:

Statement配置包含了数个与SQL Statement相关的节点,分别为:

u statement: 最为通用,它可以替代其余的所有节点。

u insert

u delete

u update

u select

u procedure

参数描述:可以是类、基本数据类型和MAP进行传值

参数

描述

parameterClass

参数类。指定了参数的完整类名(包括包路径)。

可通过别名避免每次重复书写冗长的类名。

resultClass

结果类。指定结果类型的完整类名(包括包路径)

可通过别名避免每次重复书写冗长的类名。

parameterMap

参数映射,需结合parameterMap节点对映射关系加以定义。对于存储过程之外的statement而言,建议使用parameterClass作为参数配置方式,一方面避免了参数映射配置工作,另一方面其性能表现也更加出色。

resultMap

结果映射,需结合resultMap节点对映射关系加以定义。

cacheModel

statement对应的Cache模块。

动态映射:

<select id="getUsers" parameterClass="user" resultClass="user">

Select id,name,sex from t_user

<dynamic prepend="WHERE">

<isNotEmpty prepend="AND" property="name">

(name like #name#)

</isNotEmpty>

<isNotEmpty prepend="AND" property="address">

(address like #address#)

</isNotEmpty>

</dynamic>

</select>

Ø 一元判定: 是针对属性值本身的判定,如属性是否为NULL,是否为空值等。

一元判定节点有:

节点名

描述

<isPropertyAvailable>

参数类中是否提供了此属性

<isNotPropertyAvailable>

与<isPropertyAvailable>相反

<isNull>

属性值是否为NULL

<isNotNull>

与<isNull>相反

<isEmpty>

如果属性为Collection或者String,其size是否<1,

如果非以上两种类型,则通过

String.valueOf(属性值)

获得其String类型的值后,判断其size是否<1

<isNotEmpty>

与<isEmpty>相反。

Ø 二元判定

二元判定有两个判定参数,一是属性名,而是判定值,如

<isGreaterThan prepend="AND" property="age" compareValue="18">

(age=#age#)

</isGreaterThan>

其中,property="age"指定了属性名”age”,compareValue=”18”指明了判定值为”18”。上面判定节点isGreaterThan 对应的语义是:如果age 属性大于

18(compareValue),则在SQL中加入(age=#age#)条件。

二元判定节点有:

节点名

属性值与compareValues的关系

<isEqual>

相等。

<isNotEqual>

不等。

<isGreaterThan>

大于

<isGreaterEqual>

大于等于

<isLessThan>

小于

<isLessEqual>

小于等于

posted @ 2008-08-29 12:07 小马歌 阅读(1685) | 评论 (0)编辑 收藏
 
好用的东东

/Files/xiaomage234/uu.rar
posted @ 2008-08-25 17:33 小马歌 阅读(190) | 评论 (0)编辑 收藏
 
因为第一次登录并保存密码之后,会缓存到本地,所以要删除这么一个缓存文件。
地址是: %APPDATA%\Subversion\auth\svn.simple
posted @ 2008-08-21 10:25 小马歌 阅读(1019) | 评论 (1)编辑 收藏
 
今天准备安装一个Bugzilla为工作提供方便。
准备:下载Mysql,Bugzilla,Apache

安装:
1、Mysql安装
  我是到Mysql官方网站下载For Suse的rpm包(下载了所有的rpm包,本来只安装了server包,不过最后因为缺包而中断安装)。
  安装所有的Mysql包:
  #rpm -ivh Mysql-*

  最后就是对数据库进行设置:
  #mysql
    mysql>create database bugs;
    mysql>GRANT SELECT, INSERT,UPDATE, DELETE, INDEX, ALTER,CREATE,LOCK TABLES,CREATE TEMPORARY TABLES, DROP, REFERENCES ON bugs.* TO bugs@localhost IDENTIFIED BY 'bugs';
    mysql>FLUSH PRIVILEGES;
    mysql>quit

  这样就建了一个bugs表;一个用户名为bugs,密码的Mysql用户。

2、安装Apache
  到Apache官方网站下载源代码。
  #./configure
  #make
  #make install

安装完毕。
启动Apache
  #./apachectl start
不过这里是用root来启动的,如果切换到其它用户启动就会抛出错误,说没有权限,在网上找了些资料,但最终也未能完全解决。

3、安装Bugzilla
  到官方网站下载Bugzilla
  #tar zxvf bugzilla-2.22-...
  #cd bugzilla-2.22-...
  #./checksetup.pl
  这样就会检测出来Perl需要安装的模块。然后根据列出的提示信息下载安装Perl模块。(这个比较方便的)而且只需要安装那些必要的模块就可以了。
  当
  #./checksetup.pl能正常执行完毕时,在当前目录下就会生成一个文件:localconfig
  然后,需要修改localconfig文件,这样就可以对Bugzilla的设置进行修改。
在这里你可以对数据库表名,用户名和密码进行配置。
  修改好之后再次运行:
  #./checksetup.pl
  如果正常则表示安装成功

4、配置Apache
  配置Apache是一个比较郁闷的事情,因为以前都没有好好地接触过Apache。
如果熟悉Apache的配置文件就很容易了。
  下面给出一些有用的配置:
配置文件可能是apache2.conf和httpd.conf
找到文件,然后做以下操作:
找到
AddHandler cgi-script .cgi
把注释去掉
添加以下配置
Alias /bugzilla/ "/usr/local/apache2/cgi-bin/bugzilla/"
<Directory "/usr/local/apache2/cgi-bin/bugzilla/">
   AddHandler cgi-script .cgi
   Options +Indexes +ExecCGI
   DirectoryIndex index.cgi
   AllowOverride Limit
</Directory>

基本上这样安装就完全结束了。

然后重启apache
最后就可以访问了
posted @ 2008-08-14 12:30 小马歌 阅读(940) | 评论 (0)编辑 收藏
 
 
<!-- 这些指令组件关闭JMX MBeans支持 -->
<!-- 你也可以通过包含你自己的mbean描述文件配置自定义的组件,然后设置
      “descriptors”属性为以“;”为分隔的文件名列表严将它添加到默认列表
      中,例如:descriptors="/com/myfirm/mypackage/mbean-descriptor.xml"。
-->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" debug="0" />
<!-- Global JNDI resources -->
<!-- 全局JNDI资源 -->
<GlobalNamingResources>
      <!-- 出于示例目的的测试入口 -->
      <Environment name="simpleValue" type="java.lang.Integer" value="30" />
      <!-- 可编辑的,用来通过UserDatabaseRealm认证用户的用户数据库 -->
      <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase"
       description="User database that can be updated and saved">
      </Resource>
      <ResourceParams name="UserDatabase">
       <parameter>
        <name>factory</name>
        <value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
       </parameter>
       <parameter>
        <name>pathname</name>
        <value>conf/tomcat-users.xml</value>
       </parameter>
      </ResourceParams>
</GlobalNamingResources>
<!-- 一个“Service”是一个或多个共用一个单独“Container”(容器)的“Connectors”
      组合(因此,应用程序在容器中可见)。通常,这个容器是一个“Engine”
      (引擎),但这不是必须的。
      注意:一个“Service”自身不是一个容器,因此,在这个级别上你不可定义
      诸如“Valves”或“Loggers”子组件。
-->
<!-- 定义Tomcat的标准独立服务 -->
<Service name="Catalina">
      <!-- 一个“Connector”(连接器)代表一个请求被接收和应答所需要的端点。每个连
       接器通过相关的“Container”(容器)处理请求。
       默认情况下,一个非SSL的HTTP/1.1的连接器被绑定在端口8080。你也可以通过
       根据后面的使用说明并取消第二个连接器入口的注释,在端口8443上建立一个
       SSL HTTP/1.1的连接器。开放SSL支持需要下面几步(参见Tomcat 5文档中怎样
       配置SSL的说明以取得更多的详细信息):
       * 如果你的JDK是1.3或1.3以前的版本,下载安装JSSE 1.0.2或以后版本,并放
       置JAR文件到“$JAVA_HOME/jre/lib/ext”目录下。
       * 带一个“changeit”的口令值执行:
       %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA (Windows)
       $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA (UNIX)
       来生成它自己的证书私钥。
       默认情况下,当一个web应用程序调用请求时,DNS查询是可行的。这将对性能造
       成一些不利的影响,因此,你可以将“enableLookups”设置为“false”来关闭DNS
       查询。当DNS查询被关闭时,request.getRemoteHost()将返回包含远程客户IP地
       址的字符串。
      -->
      <!-- 在8080端口上定义一个非SSL的HTTP/1.1连接器 -->
      <Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
       enableLookups="false" redirectPort="8443" acceptCount="100"
       debug="0" connectionTimeout="20000" disableUploadTimeout="true" />
      <!-- 注意,要关闭连接超时,将connectionTimeout设置为0 -->
      <!-- 注意:要使用gzip压缩需要设置如下属性:
       compression="on"
       compressionMinSize="2048"
       noCompressionUserAgents="gozilla,traviata"
       compressableMimeType="text/html,text/xml"
      -->
      <!-- 在端口8443上定义一个SSL的HTTP/1.1的连接器 -->
      <!--
       <Connector port="8443"
       maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
       enableLookups="false" disableUploadTimeout="true"
       acceptCount="100" debug="0" scheme="https" secure="true"
       clientAuth="false" sslProtocol="TLS" />
      -->
      <!-- 在端口8009上定义一个Coyote/JK2 AJP 1.3连接器 -->
      <Connector port="8009" enableLookups="false" redirectPort="8443"
       debug="0" protocol="AJP/1.3" />
      <!-- 在8082端口上定义一个代理HTTP/1.1连接器 -->
      <!-- 参见代理文档以取得这里使用属性的更多的信息。 -->
      <!--
       <Connector port="8082"
       maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
       enableLookups="false"
       acceptCount="100" debug="0" connectionTimeout="20000"
       proxyPort="80" disableUploadTimeout="true" />
      -->
      <!-- 一个“Engine”(引擎)代表处理每个请求的入口点(在Catalina内)。这个Tomcat
       的标准独立引擎实现分析包含在请求中的HTTP头信息,并将请求传送到适当的主机
       或虚拟主机上。-->
      <!-- 你应该这样设置jvmRoute以便在JK/JK2通道上支持负载平衡:
       <Engine name="Standalone" defaultHost="localhost" debug="0" jvmRoute="jvm1">
      -->
      <!-- 在我们的容器体系中定义最高级别的容器 -->
      <Engine name="Catalina" defaultHost="localhost" debug="0">
       <!-- 请求转储器值转储非常有用的通过Tomcat这个实例接收到的所有请求的,关于
        接收到的请求头和cookies,以及发送出的回应头和cookies的调试信息。如果
        你只在意一个特定的虚拟主机或者一个特定应用程序的请求,在对应的<Host>
        或<Context>入口中套用这个元素。
        对于所有的Servlet(小服务程序)2.4来所,在示例程序中检验
        “RequestDumperFilter”过滤是非常容易的(这个过滤器源代码可以在
        “$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters”下找到。
        请求转储默认情况下是关闭的,如果要使用它,取消下面行的注释符。-->
       <!--
        <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
       -->
       <!-- 全局日志设置,除非在更低的级别上覆盖它的设置 -->
       <Logger className="org.apache.catalina.logger.FileLogger"
        prefix="catalina_log." suffix=".txt" timestamp="true" />
       <!-- 因为这个Realm(区域)在这儿,因此这个实例将被全局共享。 -->
       <!-- 这个Realm(区域)使用在全局JNDI资源下,由“UserDatabase”配置的用户
        数据库。通过使用Realm将使对于这个用户数据库的任何编辑都将会立即可用
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
        debug="0" resourceName="UserDatabase"/>-->
       <!-- 注释掉旧有的Realm以便我们能很快速的恢复旧有配置。 -->
       <!--
        <Realm className="org.apache.catalina.realm.MemoryRealm" />
       -->
       <!-- 下面的属性用于从储存在数据库或从JDBC通道中得到的Realm以取代上面的
        Realm配置。-->
       <!--
        <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
        driverName="oracle.jdbc.driver.OracleDriver"
        connectionURL="jdbc:oracle:thin:@ntserver:1521:ORCL"
        connectionName="scott" connectionPassword="tiger"
        userTable="users" userNameCol="user_name" userCredCol="user_pass"
        userRoleTable="user_roles" roleNameCol="role_name" />
       -->
       <!--
        <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
        driverName="sun.jdbc.odbc.JdbcOdbcDriver"
        connectionURL="jdbc:odbc:CATALINA"
        userTable="users" userNameCol="user_name" userCredCol="user_pass"
        userRoleTable="user_roles" roleNameCol="role_name" />
       -->
       <!-- 定义默认的虚拟主机
        注意:XML模式确认将不能与Xerces 2.2同工作。
       -->
       <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true"
        autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
        <!--
         为这个结点定义一个群集,通过定义这个元素,意味着每个管理员都将被改变。
         因此,当运行一个群集时,只有确认在必须被聚集和移除其他的地方有你的
         web软件。
         一个群集有下面这些参数:
         className = 这个群集类的全限定名
         name = 你的群集的描述名,可以是任何描述
         debug = 调试级别,更高意味着更多的输出
         mcastAddr = 多播地址,所有的节点都必须有同样的多播地址
         mcastPort = 多播端口,对所有的节点都必须有同样的多播端口
         mcastBindAddr = 绑定多播套接字到一个指定的地址
         mcastTTL = 多播生存期,如果你想要限制你的广播的话
         mcastSoTimeout = 多播读取超时
         mcastFrequency = 发送“I'm alive”(我还活着)信息的间隔毫秒数
         mcastDropTime = 多长时间没有收到“I'm alive”就将这个节点标识为死节点(单位:毫秒)
         tcpThreadCount = 用于处理重复引入请求的线程数,最好是每个节点都有相同的线程数
         tcpListenAddress = 在有多块以太网卡的主机上的监听TCP群集请求的地址(绑定地址),auto意味着地址由InetAddress.getLocalHost().getHostAddress()取得。
         tcpListenPort = tcp监听端口
         tcpSelectorTimeout = 在操作系统中有java.nio唤醒错的情况下,使用Selector.select()的超时
         毫秒数。设为0则没有超时限制
         printToScreen = true意味着管理员的相关信息也将打印输出到std.out
         expireSessionsOnShutdown = true 意味着
         useDirtyFlag = true意味着我们只能在调用setAttribute,removeAttribute后才能复制一个会话;
         false意味着在每个请求后复制会话。
         false意味着复制将以下列代码方式工作:
         <%
         HashMap map = (HashMap)session.getAttribute("map");
         map.put("key","value");
         %>
         replicationMode = 可以是“pooled”、“synchronous”或者“asynchronous”
         * Pooled意味着在多个套接字上同步进行复制。例如,先复制数据,然后请求返回。
         这与“synchronous”相同,除了它使用一个套接字池,因此,它是多线程的。它是
         最快和最高级的设置,使用这个配置也增加了处理复制的tcp线程的域。
         * Synchronous指执行请求的线程,它也是向其他节点复制数据的线程,并且直到
         所有的节点都己经收到信息后才返回。
         * Asynchronous,对每个群集节点而言,这是一个特别的“sender”(发送者)线程,
         因此请求线程将复制请求排队到一个小队列中,然后,返回给用户。
         这个小队列是一个当会话被添加到队列中,而从先前的请求中,同一个会话己经存在
         ,这个会话将被放置在队列中以代替重复的两个请求。这几乎从不会发生,除非存在
         较大的网络延迟。
        -->
        <!-- 当配置群集时,你也添加一个值来捕获所有传入的请求,在请求结束时,这个会话可能被子复制,
         也可能不被复制。一个会话是否复制取决于下列条件是否发生:
         1. useDirtyFlag为真,或者setAttribute或者removeAttribute己经被调用。
         2. 会话己经存在(己经被创建了)。
         3. 请求没有被“filter”属性所捕获。
         这个filter(过滤器)属性用于过滤那些不能修改会话的请求,因此,我们在这个请求结束后不复制
         会主。这个过滤器是消极的,例如,你向过滤器发送了一些东西,然后被过滤出去,在那个匹配的过
         滤器上不会发生复制。
         过滤器属性以分号为分隔,因此你不能换行,即使你想这么做。
         filter=".*\.gif;.*\.js;"意味着在进行以.gif和.js结束的URI请求后不复制会话。
        -->
         <!--
         <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
         managerClassName="org.apache.catalina.cluster.session.DeltaManager"
         expireSessionsOnShutdown="false"
         useDirtyFlag="true">
         <Membership
         className="org.apache.catalina.cluster.mcast.McastService"
         mcastAddr="228.0.0.4"
         mcastPort="45564"
         mcastFrequency="500"
         mcastDropTime="3000"/>
         <Receiver
         className="org.apache.catalina.cluster.tcp.ReplicationListener"
         tcpListenAddress="auto"
         tcpListenPort="4001"
         tcpSelectorTimeout="100"
         tcpThreadCount="6"/>
         <Sender
         className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
         replicationMode="pooled"/>
         <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
         filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
         </Cluster>
        -->
        <!-- 通常,对每一个应用程序,用户必须逐个的认证他们自己。当他们遇到被
         某种安全约束所保护的资源时,如果你想让用户只在第一次被认证,那么,
         取消下面入口行的注释,然后在这个虚拟主机中包含这个用户的,横跨所有
         web应用程序的用户身份识别。-->
        <!--
         <Valve className="org.apache.catalina.authenticator.SingleSignOn"
         debug="0"/>
        -->
        <!-- 这个虚拟主机的所有请求的访问日志过程。默认情况下,日志文件被创建在相对
         于$CATALINA_HOME目录下的logs目录下。通过directory属性,你也可以指定一个
         不同的目录,如果你想的话。可以使用相对路径(相对于$CATALINA_HOME),也
         可以使用绝对路径。-->
        <!--
         <Valve className="org.apache.catalina.valves.AccessLogValve"
         directory="logs" prefix="localhost_access_log." suffix=".txt"
         pattern="common" resolveHosts="false"/>
        -->
        <!-- 与这个虚拟主机有关系所有上下文所共享的日志。默认情况下(使用FileLogger时),
         日志文件被创建在相对于$CATALINA_HOME目录下的logs目录下。如果你希望,你也可
         以给directory指定一个不同的路径。可以使用相对于$CATALINA_HOME的相对路径,也
         可以使用绝对路径。-->
        <Logger className="org.apache.catalina.logger.FileLogger" directory="logs"
        prefix="localhost_log." suffix=".txt" timestamp="true" />
<Context path="web上下文路径" docBase="虚拟目录路径" reloadable="true" debug="0"> </Context>
       </Host>
      </Engine>
</Service>
</Server>

tomcat文件夹的conf\catalina\localhost(对于Tomcat6版本及其以上,需要自己创建catalina和localhost这两个文件夹)
增加project .xml文件(该文件名的project要和下面的“path=“/xxx"”的xxx相同)
文件内容:
<Context path="/project" reloadable="true" docBase="E:\javastudio\oob" workDir="E:\javastudio\oob\work" />
docBase是项目文件夹的web-inf文件夹的上一层目录 workDir是指Tomcat解析Jsp转换为Java文件,并编译为class存放的文件夹,设置在项目文件夹里面,可以避免移植到其他地方首次读取jsp文件需要重新解析 。一般格式:项目文件夹\work reloadable是指可以重新加载,一般设置为true,方便使用,不需要经常重启Tomcat以后启动Tomcat,在浏览器输入http://localhost:8080/project就能访问该项目的welcome文件。

***************
为什么要不修改server.xml呢?在Tomcat6的doc帮助文档中,官方是不提倡修改server.xml来添加虚拟目录的!
       而我认为,以上使用的方法,非常方便于项目的移植,移植后,只有修改docBase和workDir的值就行了,甚至可以去掉workDir这个属性
posted @ 2008-08-14 11:45 小马歌 阅读(1159) | 评论 (0)编辑 收藏
 

通常,我们为了避免内存溢出等问题,需要设置环境变量
JAVA_OPTS    -Xms256M -Xmx512M 等,【对于服务器,一般都设置成一样的】
但是有的时候可能这样的设置还会不行(比如,当
Server应用程序加载较多类时,即jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小,为了避免调整),你可以使用更多的参数配置,如: java -Xms512m -Xmx512m -XX:PermSize=64m -XX:MaxPermSize=128m
其中,使用   -XX:MaxPerSize标志来增加永久域的大小,-XX:PerSize标志设置初始值

-XX

基于 Sun 的 Java 2 Standard Edition(J2SE)5 有生成垃圾回收功能,这允许分隔内存池以包含不同时效的对象。垃圾回收循环根据时效收集与其他对象彼此独立的对象。使用其他参数,您可以单独设置内存池的 大小。为了实现更好的性能,您应该对包含短期存活对象的池的大小进行设置,以使该池中的对象的存活时间不会超过一个垃圾回收循环。新生成的池的大小由 NewSizeMaxNewSize 参数确定。

第一次垃圾回收循环中存活下来的对象转移到另一个池中。生还者池的大小由参数 SurvivorRatio 确定。 如果垃圾回收变成了瓶颈,您可以尝试定制生成池设置。要监控垃圾回收统计信息,使用 Tivoli Performance Viewer 中的对象统计信息或 verbose:gc 配置设置。 输入下列值:
-XX:NewSize (lower bound)
-XX:MaxNewSize (upper bound)
-XX:SurvivorRatio=NewRatioSize
-XX:NewSize 320m 此值设大可调大新对象区,减少Full GC次数
-XX:+UseParNewGC :缩短minor收集的时间 可用来设置并行收集【多CPU】
-XX:+ParallelGCThreads 可用来增加并行度【多CPU】
-XX:+UseParallelGC 设置后可以使用并行清除收集器【多CPU】-Xss:每个线程的Stack大小


-verbose:gc 显示垃圾收集信息

-Xloggc:gc.log 指定垃圾收集日志文件

刚刚了解到的一些参数(待实践测试)

-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一

-XX:+UseConcMarkSweepGC :缩短major收集的时间

提示:此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适

下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M:

java –Xms128m –Xmx128m –XX:NewRatio =3

缺省值为:NewSize=2m MaxNewSize=32m SurvivorRatio=2。但是,如果 JVM 的堆大小大于 1GB,则应该使用值:-XX:newSize=640m -XX:MaxNewSize=640m -XX:SurvivorRatio=16,或者将堆的总大小的 50% 到 60% 分配给新生成的池。

          举例:永久域默认大小为4m。运行程序时,jvm会调整永久域的大小以满足需要。每次调整时,jvm会对堆进行一次完全的垃圾收集。

   使用-XX:MaxPerSize标志来增加永久域的大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小。为了避免 调整,可使用-XX:PerSize标志设置初始值。
   下面把永久域初始值设置成32m,最大值设置成64m。
    java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

默认状态下,HotSpot在新域中使用复制收集器
。该域一般分为三个部分。第一部分为Eden,用于生成新的对象。另两部分称为救助空间,当Eden充 满时,收集器停止应用程序,把所有可到达对象复制到当前的from救助空间,一旦当前的from救助空间充满,收集器则把可到达对象复制到当前的to救助 空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制,直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可 控制新域子空间的大小。

目前,我的的开发环境 2G内存,tomcat+eclipse 大型应用程序
java -Xmx1024m -XX:PermSize=512m   基本就ok大部分应用了


我的服务器参数配置:
MY_PARAMS="-Xmn340m -Xss128k -XX:NewSize=640m -XX:MaxNewSize=640m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:+UseParNewGC -Xloggc:gc.log"
posted @ 2008-08-14 11:38 小马歌 阅读(1374) | 评论 (0)编辑 收藏
 
这一段时间,Eclipse总是死掉,几乎是稍微操作快一点就会死掉,几分钟一次,搞得人郁闷至极。浪费了不少时间,在网上搜了下,看到很多朋友也出现类似的情况,在网上求救,但是网上的办法都只是说通过修改eclipse.ini文件来加大Eclipse的内存。
  
   自己试了下,发现不管用。今天,又死掉了,不过爆出一个经常出现的错误,大意是:permgen space导致内存溢出。实在忍无可忍,上网一搜,发现网络真是个好东西,尤其是对我们这种自学者而言,无疑是授业解惑的良师益友。
  
   这里总结一下自己的经验和网友的经验,希望能够对受此问题折磨的朋友有所参考价值。
  
  解决办法如下:
  
  在eclipse.ini配置文件中加上以下两行
  -XX:PermSize=128M
  -XX:MaxPermSize=128M
  
  加上上2行后,我的eclipse.ini文件如下所示:
  
  -showsplash
  org.eclipse.platform
  --launcher.XXMaxPermSize
  512m
  -vmargs
  -Xms256m
  -Xmx512m
  -XX:PermSize=128M
  -XX:MaxPermSize=128M
  
  这里的内存大小根据自己的物理内存情况来决定吧。
  
  从网上的资料看PermSize大一点肯定更好,而且最好是设置PermSize和MaxPermSize一样大。理由如下:
   PermSize 和MaxPermSize如果设置为相同还可以在一定程度上提高性能,因为,PermSize在不断的变化中会需要转移其中的数据。如果固定了以后,则可以减少每次扩大PermSize带来的性能损失。
  
  
  
  1、PermGen space简介
  
  PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。
  
  说说为什么会内存益出:
  (1)这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同。
  (2) GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。
  
  如果你的WEB APP下都用了大量的第三方jar,其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
  
  
  解决方法: 手动设置MaxPermSize大小
  
  修改TOMCAT_HOME/bin/catalina.sh,在echo "Using CATALINA_BASE: $CATALINA_BASE"上面加入以下行:
   JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
  建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存
posted @ 2008-08-14 11:37 小马歌 阅读(157) | 评论 (0)编辑 收藏
 
一 . 安装与配置MYSQL
  二 . 常用mysql命令行命令
  1 .mysql的启动与停止
  启动MYSQL服务 net start mysql
  停止MYSQL服务 net stop mysql
  2 . netstat –na | findstr 3306 查看被监听的端口 , findstr用于查找后面的端口是否存在
  3 . 在命令行中登陆MYSQL控制台 , 即使用 MYSQL COMMEND LINE TOOL
   语法格式 mysql –user=root –password=123456 db_name
   或 mysql –u root –p123456 db_name
  4 . 进入MYSQL命令行工具后 , 使用status; 或\s 查看运行环境信息
  5 . 切换连接数据库的语法 : use new_dbname;
  
  
  6 . 显示所有数据库 : show databases;
  
  7 . 显示数据库中的所有表 : show tables;
  
  8 . 显示某个表创建时的全部信息 : show create table table_name;
  
  9 . 查看表的具体属性信息及表中各字段的描述
   Describe table_name; 缩写形式 : desc table_name;
  三 。 MySql中的SQL语句
  1 . 数据库创建 : Create database db_name;
  数据库删除 : Drop database db_name; 删除时可先判断是否存在,写成 : drop database if exits db_name
  
  2 . 建表 : 创建数据表的语法 : create table table_name (字段1 数据类型 , 字段2 数据类型);
   例 : create table mytable (id int , username char(20));
   删表 : drop table table_name; 例 : drop table mytable;
  
  8 . 添加数据 : Insert into 表名 [(字段1 , 字段2 , ….)] values (值1 , 值2 , …..);
  如果向表中的每个字段都插入一个值,那么前面 [ ] 括号内字段名可写也可不写
   例 : insert into mytable (id,username) values (1,’zhangsan’);
  
  9 . 查询 : 查询所有数据 : select * from table_name;
  查询指定字段的数据 : select 字段1 , 字段2 from table_name;
  例 : select id,username from mytable where id=1 order by desc;多表查询语句------------参照第17条实例
  
  10 . 更新指定数据 , 更新某一个字段的数据(注意,不是更新字段的名字)
  Update table_name set 字段名=’新值’ [, 字段2 =’新值’ , …..][where id=id_num] [order by 字段 顺序]
  例 : update mytable set username=’lisi’ where id=1;
  Order语句是查询的顺序 , 如 : order by id desc(或asc) , 顺序有两种 : desc倒序(100—1,即从最新数据往后查询),asc(从1-100),Where和order语句也可用于查询select 与删除delete
  
  11 . 删除表中的信息 :
   删除整个表中的信息 : delete from table_name;
   删除表中指定条件的语句 : delete from table_name where 条件语句 ; 条件语句如 : id=3;
  
  12 . 创建数据库用户
  一次可以创建多个数据库用户如:
  CREATE USER username1 identified BY ‘password’ , username2 IDENTIFIED BY ‘password’….
  
  13 . 用户的权限控制:grant
   库,表级的权限控制 : 将某个库中的某个表的控制权赋予某个用户
   Grant all ON db_name.table_name TO user_name [ indentified by ‘password’ ];
  
  14 . 表结构的修改
  (1)增加一个字段格式:
  alter table table_name add column (字段名 字段类型); ----此方法带括号
  (2)指定字段插入的位置:
  alter table table_name add column 字段名 字段类型 after 某字段;
  删除一个字段:
  alter table table_name drop字段名;
  (3)修改字段名称/类型
  alter table table_name change 旧字段名 新字段名 新字段的类型;
  (4)改表的名字
  alter table table_name rename to new_table_name;
  (5)一次性清空表中的所有数据
  truncate table table_name; 此方法也会使表中的取号器(ID)从1开始
  
  15 . 增加主键,外键,约束,索引。。。。(使用方法见17实例)
  ① 约束(主键Primary key、唯一性Unique、非空Not Null)
  ② 自动增张 auto_increment
  ③外键Foreign key-----与reference table_name(col_name列名)配合使用,建表时单独使用
  ④ 删除多个表中有关联的数据----设置foreign key 为set null ---具体设置参考帮助文档
  
  16 . 查看数据库当前引擎
   SHOW CREATE TABLE table_name;
   修改数据库引擎
   ALTER TABLE table_name ENGINE=MyISAM | InnoDB;
  
  17 . SQL语句运用实例:
  --1 建users表
  create table users (id int primary key auto_increment,nikename varchar(20) not null unique,password varchar(100) not null,address varchar(200), reg_date timestamp not null default CURRENT_TIMESTAMP);
  
  --2 建articles表,在建表时设置外键
  create table articles (id int primary key auto_increment,content longtext not null,userid int,constraint foreign key (userid) references users(id) on delete set null);
  
  -----------------------------------------------------------------------
  --2.1 建articles表,建表时不设置外键
   create table articles (id int primary key auto_increment,content longtext not null,userid int);
  --2.2 给articles表设置外键
   alter table articles add constraint foreign key (userid) references users(id) on delete set null;
  ------------------------------------------------------------------------
  
  --3. 向users表中插入数据,同时插入多条
  insert into users (id,nikename,password,address) values (1,'lyh1','1234',null),(10,'lyh22','4321','湖北武汉'),(null,'lyh333','5678', '北京海淀');
  
  --4. 向article中插入三条数据
  insert into articles (id,content,userid) values (2,'hahahahahaha',11),(null,'xixixixixix',10),(13,'aiaiaiaiaiaiaiaiaiaiaiaia',1),(14,'hohoahaoaoooooooooo',10);
  
  --5. 进行多表查询,选择users表中ID=10的用户发布的所有留言及该用户的所有信息
  select articles.id,articles.content,users.* from users,articles where users.id=10 and articles.userid=users.id order by articles.id desc;
  
  --6. 查看数据库引擎类型
  show create table users;
  
  --7. 修改数据库引擎类型
  alter table users engine=MyISAM; ---因为users表中ID被设置成外键,执行此句会出错
  
  --8. 同表查询,已知一个条件的情况下.查询ID号大于用户lyh1的ID号的所有用户
  select a.id,a.nikename,a.address from users a,users b where b.nikename='lyh1' and a.id>b.id;
  ------也可写成
  select id,nikename,address from users where id>(select id from users where nikename='lyh1');
  
  9. 显示年龄比领导还大的员工:
  select a.name from users a,users b where a.managerid=b.id and a.age>b.age;
  
  查询编号为2的发帖人: 先查articles表,得到发帖人的编号,再根据编号查users得到的用户名。
  接着用关联查询.
  select * from articles,users得到笛卡儿积,再加order by articles.id以便观察
  
  使用select * from articles,users where articles.id=2 筛选出2号帖子与每个用户的组合记录
  
  再使用select * from articles,users where articles.id=2 and articles.userid=users.id选出users.id等于2号帖的发帖人id的记录.
  
  只取用户名:select user where user.id=(select userid from articles where article.id =2)
  
  找出年龄比小王还大的人:假设小王是28岁,先想找出年龄大于28的人
  select * from users where age>(select age from users where name='xiaowang');
  *****要查询的记录需要参照表里面的其他记录:
  select a.name from users a,users b where b.name='xiaowang' and a.age>b.age
  
  表里的每个用户都想pk一下.select a.nickname,b.nickname from users a,users b where a.id>b.id ;
  
  更保险的语句:select a.nickname,b.nickname from (select * from users order by id) a,(se
  lect * from users order by id) b where a.id>b.id ;
  
  再查询某个人发的所有帖子.
  select b.* from articles a , articles b where a.id=2 and a.userid=b.userid
  
  说明: 表之间存在着关系,ER概念的解释,用access中的示例数据库演示表之间的关系.只有innodb引擎才支持foreign key,mysql的任何引擎目前都不支持check约束。
  四、字符集出现错误解决办法
  出现的问题:
  mysql> update users
  -> set username='关羽'
  -> where userid=2;
  ERROR 1366 (HY000): Incorrect string value: '\xB9\xD8\xD3\xF0' for column 'usern
  ame' at row 1
  向表中插入中文字符时,出现错误。
  
  mysql> select * from users;
  +--------+----------+
  | userid | username |
  +--------+----------+
  | 2 | ???? |
  | 3 | ???? |
  | 4 | ?í?ù |
  +--------+----------+
  3 rows in set (0.00 sec)
  表中的中文字符位乱码。
  解决办法:
  使用命令:
  mysql> status;
  --------------
  mysql Ver 14.12 Distrib 5.0.45, for Win32 (ia32)
  
  Connection id: 8
  Current database: test
  Current user: root@localhost
  SSL: Not in use
  Using delimiter: ;
  Server version: 5.0.45-community-nt MySQL Community Edition (GPL)
  Protocol version: 10
  Connection: localhost via TCP/IP
  Server characterset: latin1
  Db characterset: latin1
  Client characterset: gbk
  Conn. characterset: gbk
  TCP port: 3306
  Uptime: 7 hours 39 min 19 sec
  Threads: 2 Questions: 174 Slow queries: 0 Opens: 57 Flush tables: 1 Open ta
  bles: 1 Queries per second avg: 0.006
  --------------
  查看mysql发现Server characterset,Db characterset的字符集设成了latin1,所以出现中文乱码。
  
  mysql> show tables;
  +----------------+
  | Tables_in_test |
  +----------------+
  | users |
  +----------------+
  1 row in set (0.00 sec)
  
  更改表的字符集。
  mysql> alter table users character set GBK;
  Query OK, 3 rows affected (0.08 sec)
  Records: 3 Duplicates: 0 Warnings: 0
  
  查看表的结构:
  mysql> show create users;
  ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
  corresponds to your MySQL server version for the right syntax to use near 'users
  ' at line 1
  mysql> show create table users;
  +-------+-----------------------------------------------------------------------
  ------------------------------------------------------------------------------+
  | Table | Create Table
  |
  +-------+-----------------------------------------------------------------------
  ------------------------------------------------------------------------------+
  | users | CREATE TABLE `users` (
  `userid` int(11) default NULL,
  `username` char(20) character set latin1 default NULL
  ) ENGINE=InnoDB DEFAULT CHARSET=gbk |
  +-------+-----------------------------------------------------------------------
  ------------------------------------------------------------------------------+
  1 row in set (0.00 sec)
  
  mysql> desc users;
  +----------+----------+------+-----+---------+-------+
  | Field | Type | Null | Key | Default | Extra |
  +----------+----------+------+-----+---------+-------+
  | userid | int(11) | YES | | NULL | |
  | username | char(20) | YES | | NULL | |
  +----------+----------+------+-----+---------+-------+
  2 rows in set (0.02 sec)
  
  这时向表中插入中文然后有错误。
  mysql> insert into users values(88,'中文');
  ERROR 1366 (HY000): Incorrect string value: '\xD6\xD0\xCE\xC4' for column 'usern
  ame' at row 1
  mysql> insert into users values(88,'中文');
  ERROR 1366 (HY000): Incorrect string value: '\xD6\xD0\xCE\xC4' for column 'usern
  ame' at row 1
  
  还要更改users表的username的字符集。
  mysql> alter table users modify username char(20) character set gbk;
  ERROR 1366 (HY000): Incorrect string value: '\xC0\xEE\xCB\xC4' for column 'usern
  ame' at row 1
  mysql> alter table users modify username char(20) character set gbk;
  ERROR 1366 (HY000): Incorrect string value: '\xC0\xEE\xCB\xC4' for column 'usern
  ame' at row 1
  
  因为表中已经有数据,所以更改username字符集的操作没有成***
  清空users表中的数据
  mysql> truncate table users;
  Query OK, 3 rows affected (0.01 sec)
  
  从新更改user表中username的字符集
  mysql> alter table users modify username char(20) character set gbk;
  Query OK, 0 rows affected (0.06 sec)
  Records: 0 Duplicates: 0 Warnings: 0
  
  这时再插入中文字符,插入成***。
  mysql> insert into users values(88,'中文');
  Query OK, 1 row affected (0.01 sec)
  
  mysql> select * from users;
  +--------+----------+
  | userid | username |
  +--------+----------+
  | 88 | 中文 |
  +--------+----------+
  1 row in set (0.00 sec)
  mysql>
posted @ 2008-08-13 11:20 小马歌 阅读(322) | 评论 (0)编辑 收藏
 

如果你想创建一个只包含一个源程序文件的简单程序,那么你只需要编译、连接那一个文件就可以了。如果是一个团队项目组,有着许多甚至上千个源程序文件,那么要创建一个可执行程序的过程就变得更复杂、更耗时。你必须用各种各样的组件将程序逐步建立起来。

在微软或其它一些软件公司中惯例是:每日构造并做“冒烟测试”。每天都对已完成的源程序进行编译,然后连接组合成可执行的程序,并做“冒烟测试”,以简单的检查该执行程序在运行时是否会“冒烟”。

带来的好处

虽然这是一个非常简单的过程,但却有非常重要的意义:

1、能最小化集成风险

项目组可能遇到的一个很大的风险是,项目组成员根据不同的系统功能各自开发不同的代码,但是当这些代码集成为一个系统的时候,也许系统完成不了预期的功能。这种风险的发生取决于项目中的这种不兼容性多久才被发现,由于程序界面已经发生了变化,或者系统的主要部分已经被重新设计和重新实现了,相应的排错工作将非常困难和耗时。极端情况下,集成的错误可能回导致项目被取消掉。每日构造和冒烟测试可以使这种集成错误变得非常小,而且便于解决,防止了很多集成问题的产生。

2、能减小产品低质量的风险

    这种风险是和集成不成功、集成出错相关联的。每天对集成的代码做一些少量的冒烟测试,即可杜绝项目中那些基本的质量问题。通过这种方式,使系统达到一种周知的良好状态,维护这样的系统可以防止系统逐步恶化到耗费大量时间排查质量问题的地步。

3、能简单化错误诊断

当系统每天都进行build和测试时,系统任何一天发生的错误都能够变得十分精细,便于排查。比如在17日系统还运行正常,18日就出错了,那么只需要检查这两次build之间的代码变化就可以了。

4、能极大鼓舞项目组的士气

看到产品的不断成长,能够极大的鼓舞项目组的士气,有时甚至不管这个产品到底用来做什么。开发人员可能会为系统显示了一个矩形而感到激动。通过每日构造,产品每天进步一点点,保证项目士气的持续高涨。

进行每日构造和冒烟测试

虽然说这是一个简单枯燥的活,每天进行build,每天进行测试,但也有着一些值得注意的细节:

1、每天坚持

每日构造,最重要的就是“每日”。如Jim McCarthy所说,把每日构造看作是项目的“心跳”,没有“心跳”的话,项目也就死了(Dynamics of Software Development, Microsoft Press, 1995)。Michael Cusumano and Richard W. Selby描述了另外一种隐含的比喻,把每日构造比作项目的“同步脉冲”(Microsoft Secrets, The Free Press, 1995)。 不同开发人员写的代码在他们的“脉冲”之间肯定都会存在“同步”的差异,但是必须有这样一个“同步脉冲”,使得这些代码能够组合为一个整体。当项目组坚持每天把这些不同的“脉冲”组合到一起的时候,开发人员脱离整体的情况就会得到极大程度的杜绝。

有些项目组把这一过程简化为“每周build一次”。这样带来的问题是,某一次build失败后,可能要回溯好几周才能找到原因。如果这种情况发生的话,已经得不到经常build带来的好处了。

2、严格检查每一次build

要保证每一次build的成功,就必须保证build后的结果(也可称为build)是可以正常运行的,如果build不可运行,那么本次build被认为是不成功的,同时应该将修复此次build的工作提高到项目组最高级别来处理。

对于如何衡量一个build,每一个项目组都会定义一些自己的标准,这些标准需要设定一个严格的质量级别来处理那些特别严重的缺陷,同时也需要具有一定的伸缩性来忽略掉那些微不足道的缺陷,一些不适当的关心也许会使整个过程举步为艰。

一个好的build起码应该具备以下条件:

●能够成功编译所有的文件、库,以及其它相关组件;

●能够成功链接所有的文件、库,以及其它相关组件;

●不能存在任何使得系统无法运行或者运行出错的高级别故障;

●当然,必须通过冒烟测试

3、每天进行冒烟测试

冒烟测试应该是对整个系统流程从输入到输出的完整测试。测试不必是面面俱到的,但是应该能够发现系统中较大的问题。冒烟测试应该是足够充分的,通过了冒烟测试的build就可以认为是经过充分测试、足够稳定的。

不进行冒烟测试的build是没有太大价值的。冒烟测试就像一个哨兵,在阻止着产品质量恶化和集成问题的产生,不进行冒烟测试,每日构造可能会变成浪费时间的练习。

冒烟测试必须随着系统的扩充而扩充。最初,冒烟测试可能是非常简单的,比如验证系统是否会打印“Hello World”,随着系统功能的扩充,冒烟测试需要越来越充分。最初的冒烟测试也许只需要几秒钟来执行,逐渐地,测试可能会花费30分钟,1小时,甚至更长。

4、建立一个专门的build小组

    在很多项目组,维护每日构造,并更新冒烟测试用例,会耗费一个人工作的大部分时间。因此在一些大的项目中,这项工作独立成不止一个人来完成的全职工作。比如在 Windows NT 3.0的研发中,就有一个由四个全职人员组成的专门的build小组(Pascal Zachary, Showstopper!, The Free Press, 1994)。

5、为build增加修订,如果这样做有意义的话

    一般开发人员不会每天都经常向系统中快速的增加实际的代码,通常是每隔几天,他们在开发好完成某个功能的一套代码以后,然后集成到整个系统中。

6、规定一些导致build失败的惩罚措施

很多执行每日构造的项目组都会规定一些惩罚措施,来惩罚那些导致build失败的行为。从最开始,项目组成员就清楚的知道,build的正常执行是项目组的头等大事。一个失败的build是项目组的意外,无法成为项目组工作的准则。必须坚持:导致build失败的同事,必须停下手中的工作,首先来解决build失败的问题。如果一个项目组的build经常失败的话,久而久之的,再来谈build的正确性就没有意义了。

有种轻松的惩罚措施,能够突出解决问题的优先性。Some groups give out lollipops to each "sucker" who breaks the build. This developer then has to tape the sucker to his office door until he fixes the problem. 有些项目组会惩罚犯错的同事戴上山羊角,或者向一个项目基金捐献5块钱。

有些项目组对此的惩罚就有点残酷了。微软的开发人员,在一些知名度很高、很重要的产品如Windows NT,Windows 95,Excel等产品后期研发中,被要求随时带着寻呼机,如果你的代码导致build失败的话,即使是凌晨3点钟,也会要求你立即来处理这个问题。

7、即使在压力下也需坚持每日构造和冒烟测试

当项目进度的压力越来越大时,维护每日构造的工作看起来有些浪费时间,但是恰恰相反。在压力之下,开发人员丢掉一些平时的规定,会采用一些设计和实现的捷径,这在平时压力较小的环境下一般时不会用的。代码的review和单元测试也可能会比平时粗心一些,这些代码的状态变化也会比平时快很多。

为防止这种情况的出现,每日构造会坚持相关的规定,让压力下的项目保持在正轨上。代码仍然每天在不断变化,但是构造过程使得这种变化每天都可控。

谁能够从每日构造这种过程中得到好处呢?一些开发人员会抗议说,由于他们的项目太大,每天进行build是没有实际意义的。但是为什么现在最复杂的软件项目组却能够成功的执行每日构造的制度呢?本文首发时,Windows NT包括了560万行代码、分布在4万个源程序文件中,项目组仍然可以坚持每日构造。

posted @ 2008-08-11 17:12 小马歌 阅读(268) | 评论 (0)编辑 收藏
 

Perl 是一种能完成任务的语言。

当然,如果你的工作就是写程序,那么从理论上来讲,你可以使用任何“完整”的计算机语言来完成任务。但是从我们的经验来看,计算机语言的区别很大程度上不在它能干什么,而是在它做事情的时候是否简单。从一个极端来说,那些所谓的第四代语言做某些事情的时候相当容易,但是做其它一些事情的时候几乎不可能。从另外一个极端来看,那些所谓的工业级的语言在做任何事情的时候都几乎一样困难。

Perl 是不同的语言。从一开始,Perl 就设计成可以把简单工作简单化,同时又不失去处理困难问题能力的语言。

那什么是“简单工作”呢?当然就是那些你每天都要干的。你需要一种可以很容易操作数字,文本,文件和目录,计算机和网络,特别是程序的语言。这种语言应该很容易运行外部的程序并且扫描这些程序的输出获取感兴趣的东西。而且它还应该很容易能把这些你感兴趣的东西交给其它程序做特殊的处理。当然,这种语言还应该很容易在任何现代的操作系统上可以移植地编译和运行。

Perl 做到了上述所有需求,甚至更多。

Perl 最初是当做一种 Unix 的胶水语言设计的,但是她早就移植到大多数其它操作系统里了。因为 Perl 几乎可以在任何地方运行,所以 Perl 可以说是当今最具有移植性的编程环境。要想写可移植的 C/C++ 程序,你得在程序里加上一大堆 #ifdef 标签来区分不同的系统。要想写可移植的 Java 程序,你必须理解每种新的 Java 实现的特质。要想写可移植的

shell,你可能要记住每条命令在每种操作系统上的语法,走运的时候你可能可以找到一些公共的东西。而要想写可移植的 Visual Basic 程序,那么你只需要对“移植”有个更灵活的定义就可以了。

我们很高兴的是 Perl 避免了所有这些问题,同时还保留了这些语言中的许多优点,同时还有一些自己的特色。Perl 的特色来自许多方面:它的特性集的工具,Perl 社区的创造性,以及开源运动的大环境。不过,许多这些特性都是混合的东西;Perl 的身世复杂,它总是把事物看成是优点的不同方面,而不是弱点。Perl 是“背黑锅我来”的语言。如果你觉得自己陷入一团乱麻之中,非常渴望自由,那么请使用 Perl。

Perl 是跨文化的。Perl 的爆炸性增长很大程度上是因为那些前 Unix 系统程序员的渴望,他们希望从他们的“老家”带着尽可能多的东西。对于他们而言,Perl 是可移植的 Unix 文化蒸馏器,是"此路不通"的沙漠中的绿洲。从另外一个角度来看,Perl 还可以从另外一个方向运转:在 Windows 上工作的 web 设计者通常会非常开心地发现他们的 Perl 程序可以不加修改地在 Unix 服务器上跑。

对于只是喜欢她的人来说,Perl 是实用抽取和报表语言(Practical Extractoin and Report Language)。对那些热爱她的人而言,她是变态电子垃圾制造者(Pathologically Electric Rubbish Lister)。在少数人眼里,Perl 是毫无意义的重复练习。不过世界需要一点点冗余。

/Files/xiaomage234/perl-zh-third.rar

posted @ 2008-08-09 14:44 小马歌 阅读(272) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 82 83 84 85 86 87 88 89 90 下一页 Last