随笔-6  评论-0  文章-4  trackbacks-0
  2008年7月18日
一、连接MYSQL。 

格式: mysql -h主机地址 -u用户名 -p用户密码 

1、例1:连接到本机上的MYSQL。 

首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot -p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql> 

2、例2:连接到远程主机上的MYSQL。假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令: 

mysql -h110.110.110.110 -uroot -pabcd123 

(注:u与root可以不用加空格,其它也一样) 

3、退出MYSQL命令: exit (回车) 

二、修改密码。 

格式:mysqladmin -u用户名 -p旧密码 password 新密码 

1、例1:给root加个密码ab12。首先在DOS下进入目录mysqlbin,然后键入以下命令 

mysqladmin -uroot -password ab12 

注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。 

2、例2:再将root的密码改为djg345。 

mysqladmin -uroot -pab12 password djg345 

三、增加新用户。(注意:和上面不同,下面的因为是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符) 

格式:grant select on 数据库.* to 用户名@登录主机 identified by \"密码\" 

例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MYSQL,然后键入以下命令: 

grant select,insert,update,delete on *.* to test1@\"%\" Identified by \"abc\"; 

但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据可以为所欲为了,解决办法见例2。 

例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了。 

grant select,insert,update,delete on mydb.* to test2@localhost identified by \"abc\"; 

如果你不想test2有密码,可以再打一个命令将密码消掉。 

grant select,insert,update,delete on mydb.* to test2@localhost identified by \"\"; 

在上篇我们讲了登录、增加用户、密码更改等问题。下篇我们来看看MYSQL中有关数据库方面的操作。注意:你必须首先登录到MYSQL中,以下操作都是在MYSQL的提示符下进行的,而且每个命令以分号结束。 

一、操作技巧 

1、如果你打命令时,回车后发现忘记加分号,你无须重打一遍命令,只要打个分号回车就可以了。也就是说你可以把一个完整的命令分成几行来打,完后用分号作结束标志就OK。 

2、你可以使用光标上下键调出以前的命令。但以前我用过的一个MYSQL旧版本不支持。我现在用的是mysql-3.23.27-beta-win。 

二、显示命令 

1、显示数据库列表。 

show databases; 

刚开始时才两个数据库:mysql和test。mysql库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作。 

2、显示库中的数据表: 

use mysql; //打开库,学过FOXBASE的一定不会陌生吧 

show tables; 

3、显示数据表的结构: 

describe 表名; 

4、建库: 

create database 库名; 

5、建表: 

use 库名; 

create table 表名 (字段设定列表); 

6、删库和删表: 

drop database 库名; 

drop table 表名; 

7、将表中记录清空: 

delete from 表名; 

8、显示表中的记录: 

select * from 表名; 

三、一个建库和建表以及插入数据的实例 

drop database if exists school; //如果存在SCHOOL则删除 

create database school; //建立库SCHOOL 

use school; //打开库SCHOOL 

create table teacher //建立表TEACHER 



id int(3) auto_increment not null primary key, 

name char(10) not null, 

address varchar(50) default ’深圳’, 

year date 

); //建表结束 

//以下为插入字段 

insert into teacher values(’’,’glchengang’,’深圳一中’,’1976-10-10’); 

insert into teacher values(’’,’jack’,’深圳一中’,’1975-12-23’); 

注:在建表中(1)将ID设为长度为3的数字字段:int(3)并让它每个记录自动加一:auto_increment并不能为空:not null而且让他成为主字段primary key(2)将NAME设为长度为10的字符字段(3)将ADDRESS设为长度50的字符字段,而且缺省值为深圳。varchar和char有什么区别呢,只有等以后的文章再说了。(4)将YEAR设为日期字段。 

如果你在mysql提示符键入上面的命令也可以,但不方便调试。你可以将以上命令原样写入一个文本文件中假设为school.sql,然后复制到c:\\下,并在DOS状态进入目录\\mysql\\bin,然后键入以下命令: 

mysql -uroot -p密码 < c:\\school.sql 

如果成功,空出一行无任何显示;如有错误,会有提示。(以上命令已经调试,你只要将//的注释去掉即可使用)。 

四、将文本数据转到数据库中 

1、文本数据应符合的格式:字段数据之间用tab键隔开,null值用\\n来代替. 

例: 

3 rose 深圳二中 1976-10-10 

4 mike 深圳一中 1975-12-23 

2、数据传入命令 load data local infile \"文件名\" into table 表名; 

注意:你最好将文件复制到\\mysql\\bin目录下,并且要先用use命令打表所在的库。 

五、备份数据库:(命令在DOS的\\mysql\\bin目录下执行) 
mysqldump --opt school>school.bbb 

注释:将数据库school备份到school.bbb文件,school.bbb是一个文本文件,文件名任取,打开看看你会有新发现。
posted @ 2008-10-24 09:43 chencj 阅读(140) | 评论 (0)编辑 收藏
     摘要: 最简单的 iBatis 入门例子       iBatis 是一个 O/R Mapping 解决方案, iBatis 最大的特点就是小巧,上手很快。如果你不需要太多复杂的功能, iBatis 是能满足你的要求又足够灵活的最简单的解决方案。下面我们看一个最简单的入门例子,是《 ibatis 开发指南》上的例子改的,不过上面讲的不仔细,我开始学的时候搞了一个晚...  阅读全文
posted @ 2008-08-01 11:17 chencj 阅读(802) | 评论 (0)编辑 收藏
www.x158.cn这是一个信息发布网站,他的登陆页面是在www.x158.cn/bg/login.asp
以下是利用httpclient做的一个自动登陆程序。
package test;

import java.io.IOException;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class PostForm {

    public static void main(String[] args) throws HttpException, IOException {
        UserPwd userpwd = new UserPwd("ucanhealth", "1234567");
        Zh zh = new Zh();
        System.out.println(zh.iso2utf(userpwd.getInfo())); // 打印返回结果

    }
}

class UserPwd {
    String user, pwd;

    public UserPwd(String user, String pwd) // 构造函数
    {
        this.user = user;
        this.pwd = pwd;
    }

    public String getInfo() {

        HttpClient client = new HttpClient();
        client.getHostConfiguration().setHost("www.x158.cn", 80, "http"); // url的地址,端口,协议
        PostMethod post = new PostMethod("/bg/login.asp"); // 执行查询的网页
        post.addParameter(new NameValuePair("username", user));// 传递文本框的name及values
        post.addParameter("password", pwd);// 传递文本框的pwd及values

        String s = null;
        try {

            int i = client.executeMethod(post);
            System.out.println("record statuscode:" + i);
            s = post.getResponseBodyAsString();

///////////////////////////////////////////////////////////////////////////            
            //检查是否重定向

            int statuscode = post.getStatusCode();

            if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||

                (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||

                (statuscode == HttpStatus.SC_SEE_OTHER) ||

                (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT))
            {

//    读取新的URL地址

                Header header = post.getResponseHeader("location");

                if (header != null) {

                    String newurl = header.getValue();

                    if ((newurl == null) || (newurl.equals("")))
                        

                        newurl = "/";

                    GetMethod redirect = new GetMethod(newurl);

                    client.executeMethod(redirect);

                    System.out.println("Redirect:"+ redirect.getStatusLine().toString());
              

                    redirect.releaseConnection();

                } else

                    System.out.println("Invalid redirect");

            }


//////////////////////////////////////////////////////////////////////////            
            
            
        

        } catch (HttpException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }

        return s;
    }

    class GetInfo {
        private String url;

        GetInfo(String url) {
            this.url = url;

        }

        void getInfo() throws IOException {
            String html = null;
            HttpClient hc = new HttpClient();
            // create get method instance
            GetMethod gm = new GetMethod(url);
            // 使用系统提供的默认的恢复策略
            gm.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                    new DefaultHttpMethodRetryHandler());
            try {
                int statuscode = hc.executeMethod(gm);
                if (statuscode != HttpStatus.SC_OK) {
                    System.err.print("method failed:" + gm.getStatusLine());
                    
                }
                byte[] responseBody = gm.getResponseBody();
                html = new String(responseBody);

            } catch (HttpException e) {
                System.out.println("Please check your provided http address!");
                e.printStackTrace();
            }

            System.out.println(html);
        }
    }

}

posted @ 2008-07-21 14:58 chencj 阅读(234) | 评论 (0)编辑 收藏
为什么要做batch处理    

    这个问题我就不解释了,因为我想你们肯定能比

我解释的更好!如果你真的不知道,那就到Google上去搜

索一下吧☻

Oracle回滚段

    这个问题偶也不很明白,只是大概有个了解,如

果你是这方面的专家,或者对这方面有比较深的理解,

别忘了跟偶分享哦☻

在JDBC中如何做batch处理

    JDBC提供了数据库batch处理的能力,在数据大批量操作(新增、删除等)的情况下可以大幅度提升系统的性能。我以前接触的一个项目,在没有采用batch处理时,删除5万条数据大概要半个小时左右,后来对系统进行改造,采用了batch处理的方式,删除5万条数据基本上不会超过1分钟。看一段JDBC代码:
  1. // 关闭自动执行
  2. con.setAutoCommit(false);
  3. Statement stmt = con.createStatement();
  4. stmt.addBatch("INSERT INTO employees VALUES (1000, 'Joe Jones')");
  5. stmt.addBatch("INSERT INTO departments VALUES (260, 'Shoe')");
  6. stmt.addBatch("INSERT INTO emp_dept VALUES (1000, 260)");
  7. // 提交一批要执行的更新命令
  8. int[] updateCounts = stmt.executeBatch();



    本例中禁用了自动执行模式,从而在调用 Statement.executeBatch() 时可以防止 JDBC 执行事务处理。禁用自动执行使得应用程序能够在发生错误及批处理中的某些命令不能执行时决定是否执行事务处理。因此,当进行批处理更新时,通常应该关闭自动执行。

    在JDBC 2.0 中,Statement 对象能够记住可以一起提交执行的命令列表。创建语句时,与它关联的命令列表为空。Statement.addBatch() 方法为调用语句的命令列表添加一个元素。如果批处理中包含有试图返回结果集的命令,则当调用 Statement. executeBatch() 时,将抛出 SQLException。只有 DDL 和 DML 命令(它们只返回简单的更新计数)才能作为批处理的一部分来执行。如果应用程序决定不提交已经为某语句构
造的命令批处理,则可以调用方法 Statement.clearBatch()(以上没有显示)来重新设置批处理。

    Statement.executeBatch() 方法将把命令批处理提交给基本 DBMS 来执行。命令的执行将依照在批处理中的添加顺序来进行。ExecuteBatch() 为执行的命令返回更新计数数组。数组中对应于批处理中的每个命令都包含了一项,而数组中各元素依据命令的执行顺序(这还是和命令的最初添加顺序相同)来排序。调用executeBatch() 将关闭发出调用的 Statement 对象的当前结果集(如果有一个结果集是打开的)。executeBatch() 返回后,将重新将语句的内部批处理命令列表设置为空。

    如果批处理中的某个命令无法正确执行,则 ExecuteBatch() 将抛出BatchUpdateException。可以调用BatchUpdateException.getUpdateCounts() 方法来为批处理中成功执行的命令返回更新计数的整型数组。因为当有第一个命令返回错误时,Statement.executeBatch() 就中止,而且这些命令是依据它们在批处理中的添加顺序而执行的。所以如果 BatchUpdateException.getUpdateCounts() 所返回的数组包含 N 个元素,这就意味着在调用 executeBatch() 时批处理中的前 N 个命令被成功执行。用PreparedStatement 可以象下面这样写代码:

  1. // 关闭自动执行
  2. con.setAutoCommit(false);
  3. PreparedStatement stmt = con.prepareStatement("INSERT INTO employees VALUES (?, ?)");
  4. stmt.setInt(1, 2000);
  5. stmt.setString(2, "Kelly Kaufmann");
  6. stmt.addBatch();
  7. ???
  8. // 提交要执行的批处理
  9. int[] updateCounts = stmt.executeBatch();



iBatis框架对batch处理的支持

    iBatis框架对batch处理提供了很好的支持,底层的实现方式就是JDBC。下面看一段示例代码:

  1.     private void execute(SqlMapClient client){
  2.         if(log.isDebugEnabled()){
  3.             log.debug("execute start...");
  4.         }
  5.         client.startBatch();
  6.         
  7.         for(int i=0;i<2000;i++){
  8.             client.delete("delete from order where id=?",i);
  9.             
  10.         }
  11.         client.executeBatch();
  12.         if(log.isDebugEnabled()){
  13.             log.debug("execute end...");
  14.         }
  15.     }


iBatis框架做batch处理的问题

    在一个batch中只能对一个表进行操作,例如插入或删除。当有多个表需要处理时,只能放在多个batch中进行处理。看下面的一段代码:
  1.     private void execute(int from,int to,List list){
  2.         if(log.isDebugEnabled()){
  3.             log.debug("STRGHousekeepTask execute start...");
  4.         }
  5.         HKSqlMapWrapper sqlWrapper = HKSqlMapWrapper.newInstance();
  6.         sqlWrapper.startBatch();
  7.         
  8.         for(int i=from;i<to;i++){
  9.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));
  10.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));
  11.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));
  12.         }
  13.         sqlWrapper.execBatch();
  14.         if(log.isDebugEnabled()){
  15.             log.debug("STRGHousekeepTask execute end...");
  16.         }
  17.     }
                                            代码1

    这段代码的目的就是要删除数据库中3个表的数据,sqlWrapper是iBatis的SqlMapClient的一个包装器,主要是封状对事物的控制。当批次(既to-from的值)很小的时候,这样写是没有问题的。尽管这段代码的本意是要享受batch处理带来的好处,但是事实上这段代码并不会真正达到预期的效果,至于原因,我们一会在进行分析☻。我们先来看下面一段代码:
  1.     private void execute(int from,int to,List list){
  2.         if(log.isDebugEnabled()){
  3.             log.debug("STRGHousekeepTask execute start...");
  4.         }
  5.         HKSqlMapWrapper sqlWrapper = HKSqlMapWrapper.newInstance();
  6.         sqlWrapper.startBatch();
  7.         
  8.         for(int i=from;i<to;i++){
  9.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));
  10.         }
  11.         for(int i=from;i<to;i++){
  12.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));
  13.         }
  14.         for(int i=from;i<to;i++){
  15.             sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));
  16.         }
  17.         sqlWrapper.execBatch();
  18.         if(log.isDebugEnabled()){
  19.             log.debug("STRGHousekeepTask execute end...");
  20.         }
  21.     }

                                            代码2

    正如你所看到的,和代码1相比它只是做了3次循环,每个循环执行一个表的操作。虽然麻烦,但是却真正的享受到了batch处理的好处!下面是时候解释一下这两段代码幕后的秘密了☻。
    在前面的章节里已经解释了JDBC如何做batch处理,如果还不清楚的话请查看前面的章节。要解释这两段代码里面的玄机,还得看一段代码☻下面的代码是从iBatis源码中提取的:
  1.     public void addBatch(RequestScope request, Connection conn, String sql, Object[] parameters  ) {
  2.       PreparedStatement ps = null;
  3.       if (currentSql != null
  4.           && sql.hashCode() == currentSql.hashCode()
  5.           && sql.length() == currentSql.length()) {
  6.         int last = statementList.size() - 1;
  7.         ps = (PreparedStatement) statementList.get(last);
  8.       } else {
  9.         ps = conn.prepareStatement(sql);
  10.         currentSql = sql;
  11.         statementList.add(ps);
  12.       }
  13.       request.getParameterMap().setParameters(request, ps, parameters);
  14.       ps.addBatch();
  15.       size++;
  16.     }

    这就是iBatis中batch处理的做法,在这里不想对这段代码做一一解释,有兴趣的可以自己查看一下iBatis的源码,我们只关心它如何对一条语句进行处理。参数sql是要进行batch处理的语句,parameters是sql的参数列表,如果sql和实例变量currentSql相等,则从statementList列表里面得到一个PreparedStatement,然后进行batch处理,如果不等就新生成一个PreparedStatement对象,并把它加到statementList列表里面,并把当前sql的值附给currentSql,下次传递来sql的时候就会和这个新的currentSql比较。这就是为什么在一个循环里面只对一个表进行处理的原因了。如果在一个循环里面对多个表进行处理,每次传给addBatch方法的sql都是新的,都会生成一个新的PreparedStatement,所以也就享受不到batch处理带来的好处了!    

   按照代码1的方式执行程序,当batch size很小的时候尽管享受不到batch处理带来的好处,但是也不至于会出什么大问题,但是当batch size值很大的时候(我在程序中试验过1000-5000范围),数据库就会报错了!错误是"too many courses",原因是每生成一个PreparedStatement实例,就会相应的生成一个course。假设batch size是5000,要删除10个表的数据,那么产生的course的数目就是5000*10=50000,这对数据库来说是不能接受
的,所以就会报错。

    如果按照代码2的的方式写程序肯定是没有问题的,只会生成10个PreparedStatement实例,相应的也只会生成10个course,这样就真正的享受到了batch处理带来的好处。但是,作为一名“挑剔”的程序员,我们怎么能容忍这样的写法呢?明明一个循环就可以搞定,现在要分成10个循环来做,非但效率上存在问题,大量重复的代码也让我们的程序显得很没“水准”。

    既然第一种方式不能享受batch处理带来的好处,并且还会出错,第二种方式代码又非常的丑陋,那么我们就得想个办法来解决这个问题了。请记住:解决问题的过程就是一种享受☻。

修改底层代码,支持多表batch处理

    既然出问题的地方找到了,那么解决它就很容易了。什么,你说还不知道问题出在哪?My God! Kill me ,pleale☻! 

    在这里分享一下我的思路,把每次传近来的sql作为key、把生成的PreparedStatement实例作为value放在一个Map里以后每次传来sql时先判断在Map里有没有这个key,如果有就直接拿到它的value作为PreparedStatement实例,如果没有就新生成一个PreparedStatement实例并把它放到Map里。这样有几个sql就有几个PreparedStatement
实例,和写多个循环效果是一样的。但写一个循环会更爽☻! 

后记:

      在一般的项目中做batch处理的地方似乎都是先取得一个条件列表list,然后直接根据这个list的大小作为batch size做一个循环。如果你在这个循环里同时进行多个表的CUD操作,那么这里就有一个安全隐患存在。当你的list不太大的时候,你怎么测试程序它都不会出问题,尽管可能会有执行效率上的问题,但是当突然有一天这个list变的很大的时候,你的程序可能就突然“罢工”了。 

  对于这个问题,我在上面的文档里提出了改进batch处理的方法,另外还有需要注意的一个问题就是这个list的大小的问题。如果这个list的size有可能会很大,那么我们应该考虑根据这个list的大小“分批”执行。因为并不是batch size越大效果就越好,如果batch的size很大的话很可能产生效率和性能上的问题。至于这个batch size的值为多少比较合适就没有一个固定的说法,这个可能要取决于你所使用的服务器和数据库的性能了,另外不同厂商的JDBC驱动也会有不同的性能表现,你可以向DBA咨询相关的问题。 

  我们应该尽可能把问题扼杀在摇篮之中。除了改进iBatis的batch处理机智外,还应该适当的规划batch size大小,以避免发生问题,提高执行效率。 

  上述是我个人的观点,有些地方可能不是很准确。如果你的程序中存在类似的问题,可以适当参考一下我的意见,最好还是向专业人士咨询。


有猫相伴的日子 2006-12-18 15:11 发表评论

文章来源:http://www.blogjava.net/pdw2009/archive/2006/12/18/88554.html
posted @ 2008-07-18 15:37 chencj 阅读(460) | 评论 (0)编辑 收藏
     摘要: < person >      < id > 1 </ id >     < firstName > Clinton </ firstName >...  阅读全文

有猫相伴的日子 2007-01-04 21:31 发表评论

文章来源:http://www.blogjava.net/pdw2009/archive/2007/01/04/91844.html
posted @ 2008-07-18 15:37 chencj 阅读(131) | 评论 (0)编辑 收藏
1、hibernate集合映射击与集体映射的区别在集合映射的表没有主键ID,从hibernate角度来说就是没有ID属性,hibernate不会赋予它ID值,映射的从表要有主键ID,就必须要在集合映射用到实体映射


有猫相伴的日子 2007-11-01 22:27 发表评论

文章来源:http://www.blogjava.net/pdw2009/archive/2007/11/01/157613.html
posted @ 2008-07-18 15:37 chencj 阅读(119) | 评论 (0)编辑 收藏