2012年7月21日
什么是索引?
提起索引,应该不会感到陌生,若说它就是目录,大概都知道了,数据库的索引与书的目录很相似,都叫index.书的内容相当于数据库表中的数据,书的目录通过页码指向书的内容,同样,索引也记录了表中的关键值,提供了指向表中行的指针.书的目录使读者很快的找到想看的内容,而不必翻看书的每一页,索引使得数据库应用程序能够不扫描全表而找到想要的数据.
索引是不是多多益善?
索引可以创建在一列或多列的组合上,也可以在数据库表的多个列上建立不同的索引,但这些列应该是经常作为查询条件的列.需要指出的是,并不是表上的索引越多越好,在数据库设计过程中,还是需要为表选择一些合适的索引。宁缺勿烂,这是建立索引时的一个具体选择。在理论上,虽然一个表可以设置无限的索引,但表中的索引越多,维护索引所需要的开销也就越大。每当数据表中记录有增加、删除、更新变化的时候,数据库系统都需要对所有索引进行更新。
索引的分类
索引可以分为三类:聚集索引(clustered index),非聚集索引,唯一性索引(unique index).根据索引字段组成又有复合索引的说法,复合索引可以是唯一索引也可以不是唯一索引.一个表上最多创建一个聚集索引和249个非聚集索引.
创建索引的条件
(1)为经常出现在关键字orderby、group by、distinct后面的字段,建立索引。
(2)在union等集合操作的结果集字段上,建立索引。
(3)为经常用作查询选择的字段,建立索引。
(4)在经常用作表连接的属性上,建立索引。
(5)考虑使用索引覆盖。对数据很少被更新的表,如果用户经常只查询其中的几个字段,可以考虑在这几个字段上建立索引,从而将表的扫描改变为索引的扫描。
创建索引的限制
(1)限制索引数目。
(2)唯一性太差的字段不适合单独创建索引;
(3)更新频繁的字段不适合创建索引;
(4)不会做为查询条件的字段不创建索引
posted @
2012-08-18 23:09 地心引力 阅读(1475) |
评论 (0) |
编辑 收藏
存储过程和触发器都是一组SQL语句集合,他们在数据库开发过程中,在对数据库的维护和管理等任务中,以及在维护数据库参照完整性等方面,具有不可替代的作用.而触发器是一种特殊的存储过程,存储过程独立于表,具有访问和操纵数据库数据的功能,使应用程序执行效率得到进一步提高.触发器也是T_SQL语句的集合,它与表密切结合,实现表中更为复杂的业务规则.
存储过程是以一个名字存储在数据库中的,经过预编译的T_SQL语句集合,可以独立执行或通过应用程序的调用来执行.
触发器是不由用户直接调用的,而是在对表或视图中数据进行update,insert或者delete操作时自动执行.一个表或视图可以有多个触发器,每个触发器可以包含复杂的SQL语句.数据库表之间的引用完整性约束,除了可以采用主键和外键的对应约束来实现之外,还可以使用触发器,从而实现更复杂的用户定义完整性约束.
posted @
2012-08-18 23:09 地心引力 阅读(1171) |
评论 (0) |
编辑 收藏
字符函数
这个函数一般接收字符作为参数,并且可以返回字符或数字
其中最常用有以下两个函数
1.CONCAT函数
主要用于字符串的连接,具体语法如下
CONCAT(c1,c2)
接收两个参数,将第二个参数连接到第一个参数的末尾,假如第二个参数是NULL,
则函数返回第一个参数,假如第一个参数是NULL,则参数返回第二个参数,
假如都为NULL,则函数返回NULL
为商品价格添加元单位示例如下:
2.NVL函数
这个函数主要用于函数替换
NVL(e1,e2)
接收两个参数,假如第一个参数不为NULL时,函数返回第一个参数,
假如第一个参数为NULL时,函数返回第二个参数
具体的使用示例如下:
查询商品表的相关信息,对没有详细介绍的商品默认设置显示“暂无详细描述”
可使用暂无详细描述来代替NULL
字符常用函数还有很多,希望大家能在我的基础上评论补充
posted @
2012-08-18 23:08 地心引力 阅读(1148) |
评论 (0) |
编辑 收藏
SQL语言是一种高级的非过程化的查询语言,用户使用它主要进行数据库的操作
可以把SQL语言看成是客户端与服务器端沟通的一个工具,用来存取,查询和更新,关系数据库系统
Insert语句
INSERT语句的语法结构如下:
table值的是要插入数据的表的表名,Column指的是要插入数据的列名,Value指的是要插入的具体数据值
例如往会员表中插入一个新的会员数据,可以这样添加:
前者的优点是可以指定哪些字段添加哪些数据,缺点是表名后面的小括号中的字段名需要和Value值相对照
后者的优点是书写简单,缺点是要把所有的字段都在Value中进行赋值
当需要插入数据包含有空值的时候,一般使用第一种方法,而第二种方法进行插入需要使用NULL关键字进行填充
假如插入的数据包含时间,而且时间是当前的时间,
假如插入的是时间,并且时间是某个具体的时间,我们可以将上述的语句进行修改如下:
以上操作的都是单行的数据,而下面的操作是多行的数据
插入多行数据示例如下:
UPDATE语句
UPDATE语句结构如下:
如初始化所有会员密码:
按条件更新:
做更新操作的时候,WHERE条件一般选择类似主键这样有唯一性约束的字段,除非特殊情况,
否则的话会引起意想不到的误操作,比如更新用户表时以name作为条件的话,就十分危险,
因为名字是可以重复的
Select语句
我们对数据库做得最多的操作是数据检索
select语句就显得极其重要
其中最简单的查询实例如下:
*指的是所有列
而查询所有VIP数据如下:
查询两个条件同时成立的示例如下:
查询两个条件成立其中一个,示例如下:
查询条件为空的示例如下:
当要查询会员中所有姓李的会员时,需要用到模糊查询:
% 能匹配0到多个字符
_ 能任意匹配单个字符
查询商品表中价格在300-400之间的商品数据;
而查询会员表中张三、李四、王五的信息方法如下:
使用别名查询:
其中查询中可能需要对查询的结果进行排序,其结构如下:
查询商品表,按上架时间进行排序:
如果想去掉查询结果中的重复数据,可以使用Distinction关键字,如下
Delete语句
语法结构如下
其中的table 和 condition在上面已经有提及
删除示例如下
在实际操作中我们应该使用假删除,就是再增加一个状态(一般为status)的字段
在删除错误之后,我们可以用 ROLLBACK来回滚事务
posted @
2012-08-18 23:08 地心引力 阅读(1168) |
评论 (0) |
编辑 收藏
摘要: 管理数据完整性一 学习目标 1.实现数据完整性约束 2.管理完整性约束 3.从数据字典中获取约束信息二 保证数据完整性的方法 1.应用程序代码控制 2.触发器控制 3.声明完整性约束三 约束的类型 (见图) 1.not null (不能为空) ...
阅读全文
posted @
2012-08-18 23:07 地心引力 阅读(1326) |
评论 (0) |
编辑 收藏
linux是一个多用户,多任务的操作系统,对于每一个文件它的属性中都包括:文件所有者(owner),文件所属组(group),其他用户(other),还必须具备与这三个角色对应的读,写,执行的权限,如下图:
在tmp目录下面有一个a.txt文件,我们通过ls -l命令可以查看其详细信息:
-:表示普通文件,d:表示目录文件,l:链接文件,b:设备文件中可以供存储的接口设备,c:设备文件中串行端口设备如键盘。
由于最前面是-:所以a.txt是普通文件。
再看 rw-r--r--部分,我们将其分为三组,分别对应文件所有者,文件所属组,其他用户的权限.
其中r代表读取权限,w:代表写权限,x:代表执行权限(这里没出现),-:代表没有某种权限。
那对上面的权限的解释就是:
owner:可以读和写,不能执行
group:可以读取不能写,不能执行
other:可以读取,不能写,不能执行
第一个root代表文件所有者,第二个root代表文件所属组
那么现在我如果想修改文件所有者,文件所属组,文件权限该怎么做,请继续向下阅读:
chgrp:修改用户所属组,chown:修改文件所有者,chmod:修改文件权限
假设我的系统中又一个叫gavin的组(通过/etc/group查看)
如上图,通过chgrp命令将该文件的group修改为了gavin
下面修改其所有者:
修改其权限:
chmod 777 a.txt 这个777代表什么?
在linux中使用数字代表权限:
r:4 w:2 x:1
r-- =4+0+0=4;
rw- =4+2+0=6;
rwx =4+2+1=7
相信写到这里大家都应该明白了吧。
权限对于文件和文件夹的意义是不一样的,
对于文件:
r:代表可以读取文件的内容,w:代表可以修改文件的内容,x:可以执行这个文件
对于文件夹:
r:可以获取文件夹中又哪些文件,w:可以添加和删除文件夹中的内容,x:可以进入文件夹,
如果某个角色对于一个文件夹的权限是rw-;
那么他仅仅可以使用ls获取文件夹中的内容,但是不可以使用cd进入该文件夹。
文件的权限告一段落,现在来看看linux中的那些常见目录中的内容:
/bin 系统有很多放置执行文件的目录,但是/bin比较特殊,因为/bin放置的是在单用户维护模式下还能够被操作的命令,在/bin下面的命令可以被root和一般账户使用,如:cat,chmod,chown,data,mv,mkdir,cp ,bash等常用命令。
/boot 主要放置开机使用到的文件
/dev 在linux系统中任何设备与接口设备都是以文件的形式存在于这个目录当中,你只要访问某个文件就相当于访问该设备
/etc 系统的主要配置文件几乎都在这个文件夹类。
/home 这是系统默认的用户主文件夹
/lib 系统的函数库非常多,二/lib放置的是开机会使用到的函数库
/mnt 如果你想临时挂在一些外部设备(光盘)一般建议放置到这个目录。
/opt 这是给第三方软件放置的目录
/root 系统管理员的主文件夹
/tmp 这是让一般用户或者正在执行的程序放置文件的地方,这个目录是任何人都可以访问的,所以你需要定期清理一下,当然重要数据时不能放到这里来的。
关于文件权限的最后一点就是:文件默认权限umask
现在我们已经知道如何新建或者改变一个目录的属性了,不过你知道当你新建一个新的文件或则目录是,它的默认权限是什么吗?那就是于umask这东西有关了,那么umask是在搞什么呢,基本上,umask就是制定目前用户在新建文件或目录的时候权限的默认值,如果获得或设置umask,方法如下:
#umask 或则 umask -S
(四位数,第一位我们先不管,表示特殊权限,我们从第二位开始看起)
在默认权限上,文件和目录是不一样的,对于一个目录,x权限是非常重要的 ,而对于一个文件,x权限在默认是不应该有的,因为文件大多是用来存储数据的,所以在linux中,文件的默认权限是666,目录的默认权限是777
要注意的是umask的分数指的是“默认值需要剪掉的权限”,
所以新建文件时权限:rw--r--r--
新建目录:r-xr-xr-x
posted @
2012-08-08 23:41 地心引力 阅读(1036) |
评论 (0) |
编辑 收藏
#include <stdio.h>
#include <stdlib.h>
/*判断用户输入的字符串是否为回文
*回文是指顺读和反读都一样的串
*例:abccba为回文,abcdab不是回文
*/
int Palindrome(const char *str)
{
int length = strlen(str);
for(int i = 0; i <= length/2; i++)
{
if(str[i] != str[length-i-1])
{
return -1;
}
}
return 1;
}
int main()
{
char s[100];
gets(s);
int result = Palindrome(s);
if(result == 1)
{
printf("字符串是回文");
}
else
{
printf("字符串不是回文");
}
}
posted @
2012-08-08 23:40 地心引力 阅读(6379) |
评论 (2) |
编辑 收藏
package com.xtfggef;
public class SelectSort {
/**
* @param args
*/
public static void main(String[] args) {
int[] data = new int[]{2,3,4,1,9,8};
System.out.println("before sorted:");
for(int k=0; k<data.length; k++){
System.out.print(data[k]+" ");
}
System.out.println();
int length = data.length;
for(int i=0; i<length-1; i++){
int flag = i;
for(int j=i+1; j<length; j++){
if(data[flag]>data[j]){
flag = j;
}
}
if(flag!=i){
int temp=0;
temp=data[i];
data[i]=data[flag];
data[flag]=temp;
}
}
System.out.println("after sorted:");
for(int h=0; h<data.length; h++){
System.out.print(data[h]+" ");
}
System.out.println();
}
}
posted @
2012-08-08 23:39 地心引力 阅读(826) |
评论 (0) |
编辑 收藏
一.单行函数介绍
---单行函数对单行操作
---每行返回一个结果
---有可能返回值与原参数数据类型不一致(转换函数)
---单行函数可以写在SELECT,WHERE,ORDER BY子句中
---有些函数没有参数,有些函数有一个或多个参数
---函数可以嵌套
分类:字符函数,数字函数,日期函数,转换函数,通用函数
二.字符函数
1.简介
定义:主要指参数类型是字符型,不同函数返回值可能是字符或数字类型
<1>.LOWER:全小写
LOWER('SQL Course')——>sql course
<2>.UPPER:全大写
UPPER('SQL Course')——>SQL COURSE
<3>.INITCAP:首字母大写
INITCAP('SQL Course')——>Sql course
<4>.CONCAT:字符串连接
CONCAT('Good','String')——>GoodString
<5>.SUBSTR:字符串截取
SUBSTR('String',1,3)——>Str
<6>.LENGTH:返回字符串长度
LENGTH('String')——>6
<7>.INSTR:返回一个字符串在另一个字符串中的位置
INSTR('String','r')——>3
<8>.LPAD:左填充
LPAD(sal,10,'*')——>******5000
<9>.RPAD:右填充
RPAD(sal,10,'*')——>5000******
<10>.TRIM:去掉左右两边指定字符
TRIM('S' FROM 'SSMITH')——>MITH
<11>.REPLACE:替换字符串
REPLACE('abc','b','d')——>adc
三.数字函数
<1>.ROUND:四舍五入函数
ROUND(12.3)——>12
ROUND(12.5)——>13
<2>.TRUNC:截断函数
TRUNC(65.654,0)——>65
TRUNC(65.654,-1)——>60
<3>.MOD:取余函数
MOD(10,12)——>10
MOD(7,12)——>7
MOD(10,4)——>2
四.日期函数
<1>.SYSDATE:返回系统日期
<2>.MONTHS_BETWEEN:返回两个日期间隔的月数
select months_between('02-2月-06','02-2月-06') from dual;
<3>.ADD_MONTHS:在指定日期基础上加上相应的月数
select add_months('02-2月-06',8) from dual;
<4>.NEXT_DAY:返回某一日期的下一个指定日期
select next_day('1-2月-12','星期一') next_day from dual;
<5>.LAST_DAY:返回指定日期当月最后一天的日期
select last_day('1-2月-12') last_day from dual;
<6>.ROUND(date[,'fmt'])对日期进行指定格式的四舍五入操作,按照YEAR、MONTH、DAY等进行四舍五入
SELECT employee_id, hire_date, ROUND(hire_date, 'MONTH') FROM employees WHERE SUBSTR(hire_date,-2,2)='98';
<7>.TRUNC(date[,'fmt'])对日期进行指定格式的截断操作。按照 YEAR、MONTH、DAY等进行截断
SELECT employee_id, hire_date, TRUNC(hire_date, 'MONTH') FROM employees WHERE SUBSTR(hire_date,-2,2)='98';
<8>.EXTRACT:返回从日期类型中取出指定年、月、日
SELECT last_name, hire_date, EXTRACT (MONTH FROM HIRE_DATE) MONTH FROM employees WHERE department_id = 90;
五.转换函数
---通常在字符类型、日期类型、数字类型之间进行显性转换。
<1>.TO_CHAR(date|number|'fmt'):把日期类型/数字类型的表达式或列转换为字符类型
--‘fmt’:指的是需要显示的格式,需要写在单引号中,并且是大小写敏感,可包含任何有效的日期格式
常用日期格式:
---YYYY:4位数字表示年份 ---DY:星期的英文前三位字母
---YY:两位数字年份,但是无世纪转换 ---DAY:星期的英文拼写
---RR:2位数字表示年份,有世纪转换 ---D:数字表示一星期的第几天,星期天是一周的第一天
---YEAR:年份的英文拼写 ---DD:数字表示一个月中的第几天
---MM:两位数字表示月份 ---DDD:数字表示一年中的第几天
---MONTH:月份英文拼写 ---AM或PM:上下午表示
---HH 或HH12或HH24:数字表示小时 ---MI:数字表示分钟
HH12代表12小时计时,HH24代表24小时计时 ---SS:数字表示秒;
特殊格式:
TH:显示数字表示的英文序数词,如:DDTH显示天数的序数词
SP:显示数字表示的拼写
SPTH:显示数字表示的序数词的拼写
select to_char(sysdate,’ddspth’) from dual;
“字符串”:如在格式中显示字符串,需要两端加双引号
select to_char(sysdate,’dd “of” month ‘) from dual;
数字到字符型转换:
进行数字类型到字符型转换,格式中的宽度一定要超过实际列宽度,否则会显示为###
-- 9:一位数字
-- 0:一位数字或前
-- $:显示为美元符
-- L:显示按照区域
-- .:小数点
-- ,:千位分割符
select to_char(9832, '$9,999.00') from dual;
<2>.TO_NUMBER(char[,’fmt’]): 把字符类型列或表达式转换为数字类型
select to_number('9832', 9999) from dual;
<3>.TO_DATE(char[,‘fmt’]): 把字符类型列或表达式转换为日期类型
select to_date('20120304', 'yy-mm-dd') from dual;
六.通用函数
<1>NVL(表达式1,表达式2)函数:该函数功能是空值转换,把空值转换为其他值,解决空值问题。如果表达式1为空,则表达式2就是要转换成的值。
注意:数据格式可以是日期、字符、数字,但数据类型必须匹配
select nvl(null,1) from dual;
select nvl(2,1) from dual;
<2>.NVL2(表达式1, 表达式2, 表达式3)函数:该函数是对第一个参数进行检查。如果第一个参数不为空,则输出第二个参数,如果第一个参数为空,则输出低三个参数,表达式1可以为任何数据类型。
select nvl2(null,1,2) from dual;
select nvl2(3,1,2) from dual;
<3>.NULLIF(表达式1,表达式2)函数:该函数主要完成两个参数的比较。当两个参数不相等时,返回值是第一个参数值;当两个参数相等时,返回值是空值。
select nullif(1,1) from dual;
返回值是:不是null;
select nullif(1,2) from dual;
<4>.COALESCE(表达式1, 表达式2, ... 表达式n)函数:该函数是对NVL函数的扩展。COALESCE函数功能是返回第一个不为空的参数,参数个数不受限制。
select coalesce(null,null,0,1) from dual;
<5>.CASE表达式:
SELECT last_name, commission_pct,
(CASE commission_pct
WHEN 0.1 THEN '低'
WHEN 0.2 THEN '中'
WHEN 0.3 THEN '高'
ELSE '无'
END) Commission
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY last_name;
<6>.DECODE函数:
DECODE(字段|表达式, 条件1,结果1[,条件2,结果2…,][,缺省值])
select last_name, commission_pct,decode( commission_pct,0.1,'低',0.2,'中',0.3 , '高','无') commission
from employees where commission_pct is not null orderbylast_name;
posted @
2012-08-01 22:05 地心引力 阅读(752) |
评论 (0) |
编辑 收藏
刚开始学习存储过程的时候,就把它想象成生活中把一些东西存储在某些地方,需要的时候再把它取出来使用。而在数据库学习和总结中,才发现存储过程是一种数据库对象,是为了实现某个特定任务,将一组预编译的SQL语句以一个存储单元的形式存储在服务器上,供用户调用。
posted @
2012-08-01 22:04 地心引力 阅读(668) |
评论 (0) |
编辑 收藏
电话录音服务只是内部进行录音以及调用PhoneManager对象。许多时候服务在处理业务后需要和其它程序进行通信。.startService()和stopService()适用于调用者和服务者之间没有交互的情况,否则应该适用bindSerivce()和unbindService()方法
调用bindService()方法时:
1. 服务若没有创建
s.onCreate()--às.onBind()-à服务于访问者绑定在一起
如果访问者退出:
s.onUnBind()às.onDestroy();
2.服务已经创建
不会导致调用多次服务的创建(onCreate()和绑定(onBind()),如若解除绑定可调用unbindService()方法,系统同样会调用服务的onUnbind()-àonDestory()方法。
onBind()只有调用bindService()方法才会触发方法的调用,如果服务已经被绑定,该方法不会执行多次
onUnbind()方法只有调用unbindService()方法才会导致该方法的执行。
电话录音服务只是在服务内部进行录音以及调用PhoneManager对象,许多时候服务在处理业务后,需要和其它程序进行通信.startService()和stopservice()使用使用者和服务之间没有交互的情况,否则应该使用bindService()和unbindService()方法。
调用bindService()方法时:
1. 服务若没有创建
s.onCreate()-às.onBind()-à服务于访问者绑定在一起。
如果访问者退出:
s.onUnBind()-às.onDestroy();
2.服务已经创建
不会导致调用多次服务的创建(onCreate())和绑定(onBind()),如果解除绑定可调用unbindService()方法,系统同样会调用服务的onUnbind()-àonDestroy()方法。
onBind()只有调用bindService()方法才会触发该方法的调用。如果服务已经被绑定,该方法不会被执行多次。
onUnbind()方法只有调用unbindService()方法才会导致该方法的执行。
客户端和服务通过Ibinder对象联系在一起。bindService()方法调用时,需要Intent,ServiceConnection和flag参数,其中serviceConnection对象用于接收服务onBind()方法,返回的Ibinder对象,并且该对象会传入到第二个参数serviceConnection对应的方法中,触发方法的回调,总而言之,使用客户端持有到达service对象的引用。
posted @
2012-08-01 22:03 地心引力 阅读(826) |
评论 (1) |
编辑 收藏
一、Handler的定义:
主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button, Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
二、Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
Handler中分发消息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
三、Handler实例
(1) 子类需要继承Handler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据
以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容
01 public class MyHandlerActivity extends Activity {
02 Button button;
03 MyHandler myHandler;
04
05 protected void onCreate(Bundle savedInstanceState) {
06 super.onCreate(savedInstanceState);
07 setContentView(R.layout.handlertest);
08
09 button = (Button) findViewById(R.id.button);
10 myHandler = new MyHandler();
11 // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
12 // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
13 // (2): 让一个动作,在不同的线程中执行.
14
15 // 它安排消息,用以下方法
16 // post(Runnable)
17 // postAtTime(Runnable,long)
18 // postDelayed(Runnable,long)
19 // sendEmptyMessage(int)
20 // sendMessage(Message);
21 // sendMessageAtTime(Message,long)
22 // sendMessageDelayed(Message,long)
23
24 // 以上方法以 post开头的允许你处理Runnable对象
25 //sendMessage()允许你处理Message对象(Message里可以包含数据,)
26
27 MyThread m = new MyThread();
28 new Thread(m).start();
29 }
30
31 /**
32 * 接受消息,处理消息 ,此Handler会与当前主线程一块运行
33 * */
34
35 class MyHandler extends Handler {
36 public MyHandler() {
37 }
38
39 public MyHandler(Looper L) {
40 super(L);
41 }
42
43 // 子类必须重写此方法,接受数据
44 @Override
45 public void handleMessage(Message msg) {
46 // TODO Auto-generated method stub
47 Log.d("MyHandler", "handleMessage");
48 super.handleMessage(msg);
49 // 此处可以更新UI
50 Bundle b = msg.getData();
51 String color = b.getString("color");
52 MyHandlerActivity.this.button.append(color);
53
54 }
55 }
56
57 class MyThread implements Runnable {
58 public void run() {
59
60 try {
61 Thread.sleep(10000);
62 } catch (InterruptedException e) {
63 // TODO Auto-generated catch block
64 e.printStackTrace();
65 }
66
67 Log.d("thread.", "mThread..");
68 Message msg = new Message();
69 Bundle b = new Bundle();// 存放数据
70 b.putString("color", "我的");
71 msg.setData(b);
72
73 MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI
74
75 }
76 }
posted @
2012-08-01 22:02 地心引力 阅读(609) |
评论 (0) |
编辑 收藏
来LAMP兄弟连就是我给自己的一个新起点,相信来这里的兄弟们的想法也和我一样。无论我们来自全国的什么地方,无论我们以前有过什么不同的经历,来到这里的我们都一定是想让自己改变而有一个新的开始,好的发展。那么,既然我们来了就开始吧!
放下你的过去,放下你的经验,放下你的包袱,给自己一个新的起点,新的开始。把握在这里短短五个月的日子,奋力拼搏闯出属于自己的新气象。
在这里给大家推荐一首歌,杨培安的《梦想从心开始》,其中主要的歌词是:
梦想从心开始
歌手:杨培安
伸手抓一把阳光 乘着风翱翔
点亮四面和八方
色彩像烟火 缤纷又奔放
我要活得不一样
让心中沸腾的希望 带着我勇闯
所有坚固的城墙
身上泪和伤 凝聚无穷能量
看我发热又发光
要明天记得我名字 用我选择的方式
梦想从心开始
每一步都有不变的坚持
只有我能写下自己的精彩故事
要世界看见我样子 青春骄傲的标志
梦境从心开始
灿烂新天地 美丽好心情
未来的路 等我展翅高飞 奔驰
好的东西总要和大家分享一下,希望这首歌能给大家带来更多的阳光、更多的鼓舞,当你学习疲倦时、遇到疑惑时、遇到困难时都来听一听,以此激励和督促自己。
我最喜欢其中的这几句:
要明天记得我名字 用我选择的方式
梦想从心开始
每一步都有不变的坚持
只有我能写下自己的精彩故事
“只有我能写下自己的精彩故事”,自己的路怎么走只有自己知道也只有自己控制方向。只有自己第一时间知道自己想要什么和怎么得到它,这就是我理解的“梦想从心开始”。
在这里我祝愿我们49期的兄弟们和看过我这篇小小感受的童鞋们都能冲破险阻得到自己想要的!!!
posted @
2012-07-30 23:24 地心引力 阅读(714) |
评论 (0) |
编辑 收藏
今天是 7 月30 号,上一次的最后的规划小结应该是5.21 号吧,算起来有两期的规划小结都没有写了。索性这次就将第四期和第五期的规划小结一起写了。
在5.22 到 6.21 号
在第三期结束后的第四期了,最后只完成了ARM USB蓝牙移植这一个小的实验项目
项目又是一周,做完也就是 5.26号了,这时也是应该是在学校的第18周了吧!后来就到了考试周了,不停的考试,然后不停的突击各科的考试科目,在每天的一小段时间里,应该是从5月28开始,我不不停的在网上开始去需找一些Linux 嵌入式方向的实习职位。几乎是每天平均有3封求知邮件从我的Gmail 邮箱里发出去,当然也有很多求知信是直接从智联,51job 和大街网上发出去的。应该是平均每两天收到一个电话恢复,或者是邮件回复,但肯定不都是面试通知,因为自己当时在学校不是在北京,所以仅仅收到一些电话面试,和有些公司的面试安排,其中有redhat 的电话面试,这次电话面试真的是让我自己搞砸的,我总以为redhat 的电话面试会和英语方面有一定的关系,因为自己英语水平真的很差,所以就着重在英语上好好准备了一下,而对Linux 的基本知识只是简简单单的看了一下,总认为自己平时总是在用这些命令,要是他们问起来,我肯定能回答上来。结果就这样把电话面试搞砸了。后来反正就是不停的投简历,不停的接电话,不停的复习,然后不轻的在这一期的规划里基本都做了这些事。
6.22—7.9号
这不是一期的时间不过这也算是在这两期里面一个比较关键的时间点吧。因为在这一段时间里,估计简历申请就要都一个有结果的时间了,是否有面试安排,是自己决定去北京,去北京如何安排的关键影响因素,再加上最后都是专业课考试。突击压力也是比较大。到7月7号我们所有科目考试结束,我收到的5面试。我7月9 火车来北京,10 号到这里。11 号是一个周三的七天,就开始参加面试。面试并不想多说,毕竟只是实习生职位的一些面试经历,没多大的参考价值,也就不记录了。但是还是不免唠叨,有些招实习生职位的公司,完全是为了在招聘网站上给公司打广告去了。面试的时候提的问题,真是!罢了!不说这些了。
7.10—7.30
就如上面所说,11 号的面试挺让人失望的,并非我自己Linux 方向专业能力有问题,而是公司和自己的方向比不是很对口,无论如何最后就有点失望的回到了住所,到了第二天,12号(周四)还有面试,一大早,9点整吧,这个时间是北京公司刚开始上班的时间,有公司能挑这个时间段面试,是挺奇怪的。没办法,早早的干到面试公司,9点整,进入公司,开始面试,还是一样,实习职位面试经过不提也罢。面试成功。因为公司是做嵌入式开发板的,大多是教学用ARM 或者其他开发板之类的,有点不情愿去。中午打电话去另外一家公司,下午就转战去他们公司面试,也是我现在正在实习的公司。公司不必多说,至少方向是我喜欢的那类型。14 号(周四)下午面试通过,通知7.16号( 周一)入职实习。到目为止在公司有两个周了,那些老生常谈的在公司学习和 在学校学习很有差距的话我就不多写了,经历过就知道了。项目紧天天加班,周末也不例外。但自己毕竟是一个实习生,有时总感觉心有余而力不足啊。虽然在学校的实验项目也没少做,但学校的实验项目,所有代码都是从网上下载,修改来的。而现在让你写,真的不行,曾经的自大,曾经的不可一世,到现在早已经完全没有了,现在有的就是默默的,虚心的,慢慢的,勤勤恳恳的学习和练习工作。那么在过去的两个月里,过去的没得改,就写写。以后的,我不要永远做菜鸟,我也不会永远做菜鸟。我要找到那个不可一世的自己!
posted @
2012-07-30 23:24 地心引力 阅读(647) |
评论 (0) |
编辑 收藏
背景:
有两个图片,一个是目标背景图片, 一个是带有自身背景色彩的彩色图片
先将这彩色图片绘制到目标背景图片中, 这一步通过BITBLT就可实现。 但实现后的效果是: 目标图片上,绘制上去的彩色图片带有其本身的背景。
问题就来了, 我们想将彩色图片本身的背景去掉,应该如何解决?
解决方法:
使用API函数:TransparentBlt 此函数将原DC中的图片绘制到目标DC中,并同时设置原图形在目标图形上的透明色。
- BOOL TransparentBlt(
- HDC hdcDest, // handle to destination DC
- int nXOriginDest, // x-coord of destination upper-left corner
- int nYOriginDest, // y-coord of destination upper-left corner
- int nWidthDest, // width of destination rectangle
- int hHeightDest, // height of destination rectangle
- HDC hdcSrc, // handle to source DC
- int nXOriginSrc, // x-coord of source upper-left corner
- int nYOriginSrc, // y-coord of source upper-left corner
- int nWidthSrc, // width of source rectangle
- int nHeightSrc, // height of source rectangle
- UINT crTransparent // color to make transparent
- );
如本例中,将透明色设置为彩色图形自带背景色时, 则使用此函数后,所得最终图形上彩色图形的自身背景色就消除了。
示例:
- CDC* pDC=GetDC();
-
- CBitmap bmp;
- bmp.LoadBitmap(IDB_BITMAP1);
-
- BITMAP bmpInfo;
- bmp.GetObject(sizeof(BITMAP),&bmpInfo);
-
-
- CDC ImageDC;
- ImageDC.CreateCompatibleDC(pDC);
-
- CBitmap *pOldImageBmp=ImageDC.SelectObject(&bmp);
-
-
- CBitmap bmpBK;
- bmpBK.LoadBitmap(IDB_BITMAP2);
-
- BITMAP bmpBkInfo;
- bmpBK.GetObject(sizeof(BITMAP),&bmpBkInfo);
-
- CDC bkDC;
- bkDC.CreateCompatibleDC(pDC);
-
- bkDC.SelectObject(&bmpBK);
-
- TransparentBlt(bkDC.m_hDC,100,150,bmpInfo.bmWidth,bmpInfo.bmHeight,ImageDC.m_hDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,#ff0000); // 设置红色为透明色
-
- BitBlt(pDC->m_hDC,0,0,bmpBkInfo.bmWidth,bmpBkInfo.bmHeight,bkDC.m_hDC,0,0,SRCCOPY); //画到屏幕上
原理: 通过设置掩码位图来实现
1)首先建立掩码位图
2)使用掩码位图作用于彩色原图,得到变异新图(透明色为黑,其他区域为原色)
3)使用掩码位图与目标背景图相与 (透明区域为透明色,其他区域为黑色)
4)使用变异新图与目标背景图相或 ,得到最终图
图例如下:
希望将上面小图的自身背景色去掉,得到最终图
所采取的步骤如下:
posted @
2012-07-27 22:18 地心引力 阅读(726) |
评论 (0) |
编辑 收藏
前天apple发布了最新的mountain lion操作系统,于是赶紧给mac mini升级了系统。写篇博客分享一下如何升级mountain lion。
如果你是6月11号之后购买的苹果电脑,那么你可以免费获取到升级兑换码,然后在app store里面点兑换就可以直接升级了。
如果你有mac developer的开发者帐号,你也可以登陆developer.apple.com去获取一个mountain lion的兑换码,还可以获取mountain lion server的兑换码的哦。
没有兑换码的话你可以选择花128元rmb升级,也可以自己到网上去下载一个安装包,4.34G。苹果的东西不像windows的,不是靠注册码,所以只要有安装包升级,就和花钱升级没有区别了。
具体到哪找升级包可以自己google一下哦。
忘了说,升级mountain lion,操作非常简单。不需要设置什么东西,升级完成之后会自动帮你删除掉升级包的,如果需要保存升级包全新安装mountain lion的话,请做好安装包的备份工作。
posted @
2012-07-27 22:17 地心引力 阅读(1118) |
评论 (0) |
编辑 收藏
时间:2007年5月场合:在一份Android的规格文档中话语:触屏是不可能完全代替物理按键的后续:G1手机是一款有着全键盘的手机,后续的真正的G2(不是HTC的)也是有键盘的结果:谷歌似已完全放弃了键盘手机,更不用说平板了
08年,谷歌推出了G1手机,这个手机虽然拥有键盘,但很明显,触屏功能是最主要的。两年多后,还是由t-mobile与谷歌合作,发布了真正的G2手机,也是有键盘的——这是和HTC的G2最明显的一个区别。虽然就我个人而言,还是喜欢有键盘的手机,但从大趋势上来看,触屏正在以势不可挡的力量,将键盘从移动设备中驱逐出去。
作为一个移动设备,轻便是很重要的。键盘虽然比触屏在长篇文字输入上更有优势,但牺牲的是轻便性——这个道理很浅显。但并不完全是因为这个。
电脑大致上是由输入、输出和算法三样东西构成的。输出上,今天已是液晶屏的世界,算法上则有云计算(非本地计算)的变革。输入端上,我们则看到了一系列的变化。相当古老的输入装置是磁带机,后来演变为键盘,再后来加入了鼠标以做快速屏幕定位。键盘为主鼠标为辅的输入工具,是很长一段时间的电脑标配。
我之所以用键盘为主鼠标为辅这样的字眼,概因为一台电脑不配鼠标总还是能运作,但不配键盘基本就歇菜了。这两个东西,键盘属于重输入,鼠标偏向轻输入。06年的时候,在一场会议中聆听keso的发言。他说道,在互联网上,用鼠标的人比用键盘的人多。这话背后的意思大致就是,数字世界里,看的人多,写的人少——这一点,无论是从当时的博客数据,还是今天的微博数据,都得到了印证。
在游戏世界里,用鼠标的,通常都是比较简单的游戏。而大型游戏的高手级玩法,需要动用键盘快捷键。然而,一旦脱离电脑,游戏的指令输入,就已经发生了变革。
这就是WII.WII游戏机配有一个无线遥控器,玩家手握这个遥控器做各种动作来完成指令。而到了kinect,连这个遥控器都省了——这是人体动作输入。人体动作输入(捕捉)使得使用者无需经过一定意义上的培训(使用键盘还是要小小的操练一下子的),立刻便可以上手。这也是经常可以看到很小的小孩在那里能玩iPad而玩不了电脑的原因。
触屏的动作捕捉,极大地降低了使用门槛——想想黑莓那个让人望而生畏的全键盘手机吧。智能手机的另外一个解读就是“傻瓜化使用的手机”。虽然它是高科技产品,但如果一派技术风范,是很难让最大范围上的大众产生亲近感的。
后来推出的iPad2,不仅有触屏输入,还提供了另外一种动作输入的可能,那就是这款设备提供了摄像头。Kinect就是依靠摄像头来完成人体动作捕捉的。
动作捕捉还没完,还有一种输入法也已经从实验室里走了出来,那就是语音输入。苹果的Siri推出后,出现了席卷全球的所谓“调戏Siri”的实验。语音输入目前还有一些问题(比如口音重的人很难得到好的体验),但它依然是一种傻瓜化的输入方法。
我个人一直向很多人推荐《铁甲钢拳》(Real Steel)这部好莱坞电影。从这部主要是讲机器人拳击的电影中,你会看到若干种“指令输入”。人类可以用语音来指挥机器人,还可以通过一种形似iPad的东西来触屏输入指令,最后,还可以通过自己做一些动作来机器人捕捉并效仿。对比一下其它科幻片里,人类敲击着键盘让电脑完成各种任务的场景,效率之高低,一目了然。
我总觉得一个企业并不是没有灵魂的纯粹意义上的多人集合体,企业有其根深蒂固的基因。谷歌是一个高科技公司,虽然它推出的搜索服务从使用者角度而言非常简单,但完成这个服务需要极其复杂的运算。在谷歌的习惯性思维里,复杂是一个绕不过去的潜意识。两位创始人博士虽然没有毕业,但好歹读到了这个份上,天然也是往“复杂”里靠的。坚持键盘输入,大概就是这样的意识驱动:一个可以视为电脑的智能手机,怎么可以没有键盘这种重输入装置呢?
但苹果不是,它其实是一个消费品公司。乔布斯在apple机时代就要求工程师去除电脑的散热器——这个要求在工程师里眼里很荒唐,但乔布斯的立场是:消费者会被电脑散热器的嗡嗡声搞得很烦躁。虽然乔布斯这个很荒唐的想法没有实现,但从中我们的确可以咀嚼出点什么:谷歌要造电脑,是绝不会有这个荒唐的念头的。
键鼠输入,还是有些机器本位的:人需要学习才能使用机器。动作输入(触屏或摄像头捕捉)、语音输入,则偏向人本位:人无需学习。只是不得不追问这样一句话:当我们越来越能傻瓜化地使用智能设备时,我们会不会傻瓜化呢?
posted @
2012-07-27 22:16 地心引力 阅读(743) |
评论 (0) |
编辑 收藏
创业四个月,感受颇多,几点分享:
1.一旦选择离开以前的环境创业,必须以最快的速度给自己重新定位,特别是自己以前是企业中的高管,请尽快放弃随时一副牛逼很大的样子。离开了那个组织属性,其实你什么也不是。
2.永远不要觉得自己已经掌控了一切,沉下去认真分析才是正事。当觉得自己掌控一切的时候,是个极其危险的信号,任何事情都需要有充分的风险保障考虑。
3.关系是需要用心经营的,蹲点越低,跳的越高。
4.不要选择性的去接受自己喜欢的信息,信息本身不因为个人喜好而变化,尽量的去收集信息,信息掌握越全面,做出的决策正确性越高。
5.管理三部曲:布局、造势、摆平。暗布局,明造势,借势摆平!
posted @
2012-07-27 22:14 地心引力 阅读(759) |
评论 (1) |
编辑 收藏
和大多数八零后的男孩一样,小时候就喜欢打游戏,即便是坦克大战和热血足球这样的红白机游戏,我现在还和我表弟偶尔用模拟器过 过瘾。比起现在一些炫目华丽的游戏,那些游戏无疑更加经典持久。不过今天不谈我说说我玩过的留给我回忆的那些PC游戏。有的也许你非常熟悉,有的也许你闻 所未闻。人说十年就一个代沟,程序员则是五年。
赤壁
联 想“幸福e家”(好像是这个名)电脑附带的一款即时战略游戏,由前导公司97年出品(如果你想到的是如今的网游,那么说明我们不是一个年代的人,呵呵)。 知道这款游戏的人并不多。很多老玩家知道“血狮”,这一款发售时火爆异常,但是最终丢尽中国游戏厂商脸面的游戏。可是赤壁的销量却远远超过了它——十五万 套。97年,十五万套软件是怎样一种概念?
故事太过久远,我的记忆并不丰盈。贴上一段网上翻到的介绍:“这是由前导公司继《三国之官渡》之后出品的第二部以三国为背景的即时战略游戏。游戏在 Win 95下运行,容量150MB。硬盘安装需30MB。游戏采用640×480×256色的高分辨率画面。3D的主菜单做得还算精美,界面也做得不错,人物头 像用的是电视连续剧《三国演义》的剧照,让人颇感亲切。游戏中的各种建筑古色古香,将军的士兵可从衣着分辨兵种,便于玩家操纵。游戏中共有25个兵种(如 步兵、骑兵、弓箭手、投石车)、4种船只(运输船、快船、战船、连环战船)、26种建筑(如帅帐、弓兵所、步兵所、骑兵所、箭楼、帅旗、武器库、木材场、 船坞、钱庄)、10种阵形(如梅花、连环、金锁、八卦)、9种计谋(如乱军、十面埋伏、火攻、滚木等)。游戏的生产资料是有中国特色的小麦、木材和镔铁。 通过钱庄转换为战争所需的钱。游戏中的建筑物城内的和城外的样子不同,如中军帐在城内是一座带有院墙、门外摆着石狮子的大厅,而在城外是一座大帐。游戏的 音乐气势恢弘,音效不多但很热闹。”
破碎虚空
它是我真正正儿八经地投入去玩的第一款游戏(这是一款2001年的游戏,不是后来的同名网游)。小时候打游戏的历史就是和父母斗争的历史,既要躲闪,又要 反抗。玩这款游戏也是从周末我兴冲冲骑车到同学家开始的,他的父母是老师,周末总是需要给去学校给别的孩子补课,于是老师的孩子就被放养了。当时我就特别 感慨,老师的孩子真自由。游戏改编自古龙的小说。在当时纸片一样的游戏时代里,居然有这样一款战斗画面如此绚丽的国产游戏(即使放到今天也不显得太次), 着实令我惊讶不浅。
“飞燕刀法”、“雷霆刀法”,那些游戏中武功的招式,我现在依然清晰记得。可以说,这是一款真正让我认识到什么是RPG的游戏。人对于第一次发生的 事情总是颇易感怀。如今和朋友聊天,却没有多少人知道这一款游戏,同龄人的国产单机游戏经历似乎都是从《金庸群侠传》、《轩辕剑》、《仙剑奇侠传》等等公 认经典开始的,北斗星工作室的游戏(记得后来又出了一款《仙狐奇缘》)兴许过于小众了?
上面两款游戏下载地址就不提供了,感兴趣的同学去verycd上搜吧。
最终幻想8
这 是我记忆里最唯美的日本RPG游戏,没有之一。即便是最终幻想后面几代也没有在“唯美”的意义上超过它。从游戏革命性的意义上说,它没有第七代重大,但是 对当时的我来说,游戏实在是太美了。从开场的动画开始,羽毛、花园、大海、战斗的场面,史克威尔的经典,莉诺雅和史克尔的浪漫爱情,高潮部分王菲演唱的主 题曲《Eyes On Me》,直到最后的唯美结局……
整个英文版游戏二十万字的对白,我用的是PS模拟器,我已经记不清我是怎样靠一个文曲星硬是把它啃下来的,印象中工作以前也就那一段啃游戏的时间里 英文进步最快。游戏打到最后,整个游戏过程几十个小时,我的角色都是99级,但是完全没有感觉到练级的枯燥,事实上,我根本没有想做练级这件事情。
最终幻想历代总是会放一些彩蛋,最终幻想8也一样,陆行鸟系统是里面很有意思和增加可玩性的部分,可惜的是我使用的是模拟器,当时没有在游戏之外培 养陆行鸟。召唤兽+魔法卡片系统也是值得回味的亮点之一,还记得施法画面的华丽效果,每个人物在少血时都能高概率使出必杀技。唯一遗憾的是当时没有干掉隐 藏boss奥美嘉。
泰伯利亚之日
请 注意我说的是99年的游戏,以及同一引擎下的资料片“烈焰风暴”,而不是后来推出的3D续作。westwood公司留下了红警这个传奇的游戏,但我却对泰 伯利亚之日情有独钟。这款游戏其实并不算卖座,但是2D画面却相当不错,而且兵器单元在爆破的时候演算效果也颇为到位,比起之后推出的看起来像儿童游戏的 红警3可不知好了多少。另外,游戏的制作对于细节非常重视,这在游戏中很容易体会到,比如起伏的地形对于炮弹轨迹的影响、容易破碎的冰面、行走缓慢的森林 等等。遗憾的是这款游戏平衡性做得比较差,NOD比GDI要强出许多,再一个AI也遭人诟病。不过,如果你是2D即时战略游戏的爱好者,是不能错过它的。
突然的流星雨带来了泰伯利亚矿这种能够自我生长、具备超强能量的矿物晶体。NOD和GDI双方展开了遍及欧洲和非洲的第一次泰伯利亚战争。NOD被 GDI击败后东山再起。2015年,疯狂传播的Tiberium矿物破坏了周边的生态环境和大陆的每一个城市,GDI不得不把人口转移到北极地区寻找对 策,NOD则干脆转入地下,从事他们的基因转变研究。双方都拥有非常先进的科学技术,GDI的拥有强大的空间技术和战车技术,设计出了The Wolverine、泰坦、 猛犸II型、神像等步行载具;NOD拥有强大的电脑技术和隐形技术,并且能熟练的运用泰伯利亚制作武器、装备或者新的生物。
实况足球系列
其 实足球游戏最早我是从FIFA2000开始的,换句话说,我是一个从FIFA转向实况的足球游戏迷。但是FIFA2000在那个时候确实是无可替代的,不 仅仅是画面的效果这种FIFA的强项,游戏性在当时也是非常优秀的。FIFA的操作略显复杂,我适应了好一段时间,但是习惯以后就非常舒服。后来中央五台 还直播FIFA的国际比赛,电脑报接连报道了一些FIFA战队的近况,真是火了。
之所以说它是一个系列是因为,从05年开始,每一代新发售的实况足球游戏,我都会跟上。从操作感上面来说,实况领先FIFA似乎有N年。读书的年代闲暇时间多,总是去研究怎么让人物做出各种动作,甚至背出各种奇异的bug……
现在我还在玩实况,不过年龄增长使得要求大幅度提高,玩一阵子就意兴阑珊。不过,大师联赛依然是我最常玩的游戏项目。
足球经理系列
我 玩足球经理的时间并不早,但是从来不玩汉化版,版本也只玩SI公司的。每个人心中总有一种控制别人,以及渴望被人追捧的欲望(俗称“意淫”),XX经理、 XX大亨这一类的游戏都是利用人的这一特性设计开发的。不过这一类游戏的质量可千差万别。这款游戏最早其实名字叫做冠军足球经理(CM),后来SI和 Eidos分家,Eidos得到了冠名权,而SI得到了程序版权。很明显,Eidos是短视的。冠名权可以火一时,但是这一类游戏玩的就是数据库。于是 CM逐渐被挤出市场。
我玩过大球会,也用过小球会,甚至变态到把自己球队的青年队安插到巴西甲级联赛,把预备队安插到荷兰甲级联赛去踢球。起初,我就是这样一个修改狂。 其实这样的游戏投资可以不大,没有创新,紧靠历代数据库的更新就可以延续很久。很多玩足球经理的人都想,如果能够把它和实况足球这样的模式结合起来,既可 以培养球员,有足球经理这样丰富的体验;又可以使用实况足球这样的模式踢比赛该多好!其实,几年前FIFA某一个版本已经支持将FIFA足球经理的数据放 置到FIFA足球中去踢比赛,这个想法太好了,EA也很有钱,只可惜没有坚持做下去,游戏体验上也始终没法达到第一的水准。
暗黑破坏神II
暗 黑破坏神II在我看来是一款几乎不可能被逾越的游戏了。即便是暗黑III,亦让我感到失落,它确实改进了暗黑II不足的地方,3D可以说马马虎虎(这倒还 好,毕竟暗黑系列并不以画面见长),但是游戏中的战略性,以及打击快感消失了,地狱、炼狱奇恶无比的瞬移秒杀让我无所适从。暴雪系列的游戏性绝对无可指 摘,但是游戏发展的方向似乎需要考虑考虑了。
第一幕的草地,第二幕的沙漠,第三幕的雨林,每一幕都具备鲜明的场景,第四幕显得有些仓促。冰系的魔法或者是招式都具备很强的打击感,譬如亚马逊的 冻结之箭,爆裂的效果直到现在也可以说非常过瘾。而技能系统、装备系统可以说一直是暴雪的强项,这些都是游戏耐玩性的保证。我忘记我已经用各种角色、不同 模式通关十几、或者几十遍了,如果你是RPG玩家却还没有玩过它,我强烈建议你补补功课,不过最好安装一个高分辨率的补丁。
游戏发布十年后,一款MOD都可以炒到沸沸扬扬,而暴雪还在为它提供修复bug和修正平衡性的补丁,我不相信还有哪一款单机游戏可以达到这种高度。
posted @
2012-07-26 22:32 地心引力 阅读(609) |
评论 (0) |
编辑 收藏
一直想学习怎么使用spring 的事务,在网上查了很多资料,还是不知道怎么写,大都是基于注解方式的,要么就是基于hibernate的事务,而且没有完整的例子,都是代码片段,这里我自己写了一个简单的demo,供给大家学习
1、建立一个对象(跟数据库中的表对应)
- package hb.bean;
-
- public class Book {
- private int id;
- private String name;
- private String author;
- private int num;
-
- public int getNum() {
- return num;
- }
-
- public void setNum(int num) {
- this.num = num;
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
- }
2、建立一个接口(实现对表的相关操作)
- package hb.dao;
-
- import hb.bean.Book;
- import java.util.List;
- import org.springframework.transaction.annotation.Transactional;
-
- @Transactional
- public interface BookDAO {
-
- //查看book表中的所有数据
- public List listBook();
-
- //向book表中插入一条数据
- public void insertBook(Book book);
- }
3、实现接口的操作
- package hb.dao.imp;
-
- import hb.bean.Book;
- import hb.dao.BookDAO;
- import hb.row.UserRowMapper;
-
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.List;
-
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.RowMapper;
- import org.springframework.jdbc.core.support.JdbcDaoSupport;
- import org.springframework.jdbc.datasource.DataSourceTransactionManager;
- import org.springframework.transaction.TransactionStatus;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.transaction.support.TransactionCallbackWithoutResult;
- import org.springframework.transaction.support.TransactionTemplate;
-
- import sun.jdbc.odbc.ee.DataSource;
-
- @Transactional
- public class BookDAOImpl extends JdbcDaoSupport implements BookDAO {
-
- public DataSourceTransactionManager transactionManager;
-
- public void setTransactionManager(DataSourceTransactionManager transactionManager) {
- this.transactionManager = transactionManager;
- }
-
- @SuppressWarnings("unchecked")
- public List listBook() {
- String sql = "select * from book";
- //JdbcDaoSupport里面有jdbcTemplate这个对象的set方法.JdbcTemplate这个类需要配置数据源
- List list = this.getJdbcTemplate().query(sql, new UserRowMapper());
- return list;
- }
-
- public void insertBook(final Book book) {
- final String sql = "insert into book(id,name,author,num)values(?,?,?,?)";
- TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
- final JdbcTemplate jdbcTemplate = this.getJdbcTemplate();
- transactionTemplate.execute(new TransactionCallbackWithoutResult(){
- @Override
- protected void doInTransactionWithoutResult(TransactionStatus arg0) {
- Object[] params = new Object[] {book.getId(), book.getName(), book.getAuthor(),book.getNum() };
- //下面的语句是用来测试事务异常的情况
- // new Integer("huangbiao");
- jdbcTemplate.update(sql, params);
- }
- });
-
- }
-
- }
4、继承RowMapper 接口接受返回过来的结果集
- package hb.row;
-
- import hb.bean.Book;
-
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
- import org.springframework.jdbc.core.RowMapper;
-
- public class UserRowMapper implements RowMapper {
-
- public Object mapRow(ResultSet rs,int index) throws SQLException {
- Book book = new Book();
- System.out.println(rs.getString("name"));
- book.setName(rs.getString("name"));
- return book;
- }
- }
posted @
2012-07-26 22:31 地心引力 阅读(1915) |
评论 (2) |
编辑 收藏
我们做的很多应用程序,很多功能都需要较长的加载时间,比如下载功能,转换页面等等。在程序进行后台处理的时候,前台的ui是没有反应的。如果在这段时间内我们不作任何处理就让程序停在那的话。第一,用户体验会很差。第二,如果用户在这段时间内不耐烦开始对界面猛点(我相信长时间程序没响应大家都会这么做),那么很可能使程序挂掉。所以我们需要在程序加载时弹出加载对话框,解决以上两个问题。
先给大家看一下效果图:
显示最新帖子界面:
点击最热按钮,跳转到显示最热帖子页面,在加载时弹出加载对话框:
加载完毕后,变成了最热页面:
- progressdialog=ProgressDialog.show(HTTPRequestActivity.this, "Loading...", "Please wait...",true,false);
这当中progressdialog是一个ProgressDialog的对象,show的参数依次为上下文,Dialog要显示的标题,Dialog显示的信息,第三个参数确定进度条是否为不确定,第四个确定是否可以被取消。至于你还想要设置它的其他属性,可以去查一下文档,里面有很多设置属性的函数,你可以通过这些函数把对话框改成你想要的样子。
然后我们要解决的一个问题就是如何在程序加载成功之后让对话框消失,显示新的页面内容。
代码如下:
- Handler dialoghandle=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- super.handleMessage(msg);
- progressdialog.dismiss();
- }
- };
首先定义一个Handler对象,重载其handlemessage方法,在这里面让ProgressDialog消失。
下面我以“最热”按钮为例,“最新”按钮和其基本一致。
- hotest.setOnClickListener(new OnClickListener(){
-
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method
- newest.setClickable(true);
- hotest.setClickable(false);
- progressdialog=ProgressDialog.show(HTTPRequestActivity.this, "Loading...", "Please wait...",true,false);
- seturl("http://www.bling0.com/all/hottest/day.json");
- new Thread(){
- public void run(){
- CallWebService(geturl());
- listadapter=new SimpleAdapter(HTTPRequestActivity.this,Hotlist ,R.layout.user,new String[]{"title","group","photo","username"},new int []{R.id.title,R.id.group,R.id.photo,R.id.username});
-
-
-
- dialoghandle.post(new Runnable(){
- public void run()
- {
- <span style="white-space: pre;"> </span>setListAdapter(listadapter);
- dialoghandle.sendEmptyMessage(0);
- }
- });
- }
- }.start();
- }
- });
- }
posted @
2012-07-26 22:29 地心引力 阅读(1972) |
评论 (1) |
编辑 收藏
开始合作之后,装上了SVN,非常高效,我在VS写了一部分的代码,上传之后,别人通过下载或是更新,就更新到了合作同伴的VS里,相当于大家在一个VS里写代码。和保强他们聊天的时候,发现他们与SVN关联的文件是这个样子的
...
我的怎么没有出现关联图标的(没有下面的对钩)找了下解决办法,成功的把这个问题解决掉了。
如果你也出现了这个问题,可以这样试下:在同步的文件点击右键如下图
...
现则Settings,出现的界面如下
...
选中Default之后,确定就可以了。这样更改之后,可以看一下关联文件图标更改了没有,如果没的话,咱们接着往下看:
打开注册表(运行 regedit)
这个路径: 效果图是这样的:
...
所需要作出的修改是,删除含有Tortoise关键字的前面的注册表项(进行此操作前将当前注册表文件夹备份,因为操作注册表有一定的危险性,如果出了问题可以用备份恢复),确保以Tortoise开始的项(Tortoise前面有数字)在该注册表文件夹内为前15项。
设置完成之后,重启下计算机,看机后,关联文件的图标就成功显示成了
...
那为什么这样操作呢,原理是这样的(百度到的):Windows Explorer Shell (Windows图形壳)支持的 Overlay Icon 最多 15 个,Windows 自身使用了 4 个,只剩 11 个可扩展使用,如果你之前还安装诸如 Groove 这样的软件,可能这 11 个位置都被他们剥夺了,轮不到 Tortoise 了。不过,可以给 Tortoise 优先腾出位置的:调整 Tortoise 图标名称的字母顺序。 Windows 内部就是按图标名称的字母顺序来优先显示的。
SVN是个非常好用的版本管理软件,因此拿出时间来学习它的使用和解决使用过程中的问题也是非常值得的。
posted @
2012-07-24 22:09 地心引力 阅读(10823) |
评论 (1) |
编辑 收藏
摘要: SpringMVC框架介绍Spring框架提供了构造Web应用程序的全能MVC模块。Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行制定。是一个标准的MVC框架。那你猜一猜哪一部分应该是哪一部分?SpringMVC框架图 &n...
阅读全文
posted @
2012-07-24 22:08 地心引力 阅读(4601) |
评论 (3) |
编辑 收藏
工厂模式: 一、引子 话说十年前,有一个用户,他家有三辆汽车——Benz奔驰、Bmw宝马、Audi奥迪,还雇了司机为他开车。不过,用户坐车时总是怪怪的:上 Benz车后跟司机说“开奔驰车!”, 坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”。你一定说:这人有病!直接说开车不就行了?! 而当把这个用户的行为放到我们程序设计中来时,会发现这是一个 普遍存在的现象。幸运的是,这种有病的现象在OO(面向对象)语言中可以避免了。下面就以Java语言为基础来引入我们本文的主题:工厂模式。 二、工厂模式分为: 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 1、简单工厂模式(Simple Factory) :又称静态工厂方法模式,重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。 但不利于产生系列产品。 在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。 Simple Factory 模式角色组成: 1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。 2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。 3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式: 当用户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂 类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想, 因为每增加一辆车,都要在工厂类中增加相应的业务逻辑或 者判断逻辑,这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类(在我们的例子 中是为CarFactory),我们称它为全能类或者上帝类。 我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累 坏了我们这些程序员,于是工厂方法模式作为救世主出现了; 2、工厂方法模式(Factory Method):又称为多形性工厂,工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模 式里不同的工厂子类来分担。工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。 Factory Method模式角色组成: 1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品( 即用户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的! 可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情 况,可以考虑使用简单工厂 模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。 3、简单工厂模式与工厂方法模式小结: 工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以 考虑使用工厂方法模式: 1)当客户程序不需要知道要使用对象的创建过程。 2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。 简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色 中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。 面对这种情况,Java的反射机制与配置文件的巧妙结合突破 了限制——这在Spring中完美的体现了出来。 工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式, 把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象 工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实 的工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。 4、抽象工厂模式(Abstract Factory):又称为工具箱,产生产品族,但不利于产生新的产品 什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。回到抽象工厂模式的话题上。可以说,抽象工厂模式和工厂方法模式的 区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。 使用抽象工厂模式还要满足一下条件: 1)系统中有多个产品族,而系统一次只可能消费其中一族产品。 2)同属于同一个产品族的产品以其使用。 Abstract Factory模式角色组成(和工厂方法的如出一辙): 1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。 3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。 三、总结 三种模式从上到下逐步抽象,并且更具一般性。GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式 (Simple Factory)看为工厂方法模式的一种特例,两者归为一类。 (1)简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。 (2)工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。 (3)抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。 四、个人总结 总结之前,先说两个概念,请确保理解,如下: 1. 产品:具体到某一实例,如:宝马,奔驰,J20,F35等; 2. 产品族:具体到某一类产品,如:汽车(Car),飞机(Plane)等; 简单工厂模式(Simple Factory):适用于同一产品族,固定产品种类的情况,优点:代码简单,缺点:不利于增加新产品,需修改原有工厂代码; 工厂方法模式(Factory Method):适用于同一产品族,可变产品种类的情况,优点:代码简单,利于增加新产品,无需修改原有工厂代码,缺点:子工厂类遍布各处,子工厂类易泛滥; 抽象工厂模式(Abstract Factory):适用于不同产品族情况,优点:可生产不同产品族的产品,缺点:不利于增加新产品,即使在工厂类:ProductFactoryByFactory中,使用了调用产品 Factory创建对象,在增加新产品时,依然违背了不修改原有工厂代码的原则; 五、延伸阅读 Java的开闭原则:一个软件系统应该对开展时开放的,对修改时关闭的(Software entity should be open for extension, but closed for modification);在设计一个模块的时候,应该 可以使这个模块可以在不被修改的前提下被扩张。换言之,应该可以在不必修改源代码的情况下改变这个模块的行为。 听上去很矛盾,但是通过一些使用一些设计模式就可以轻松的做到,如 适配器模式(adapter)等等。满足了OCP(Open-Closed Principle)原则可以给软件系统带来两个无法比拟的设计目标: 1.扩展性。通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求。 2.稳定性。已有的软件模块,特别是最重要的抽象层模块不能被修改,这就是变化中的软件系统有一定的稳定性和可延续性。 3.维护性大大提高。 怎么才能实现“开-闭”原则: 抽象化是关键 解决问题的关键在于抽象化。在像java这样的面向对象的语言中,可以给系统定义出一个一劳永逸,不再更改的抽象设计,此设计允许有无穷无尽的实现,并且互不影响。在java语言中,给出一个 抽象的类或者接口,规定出具体方法必须提供的方法特征作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此,在任何扩展情况下都不会改变。这就使得系统的抽象层不需要修改,从 而满足了“开-闭”原则的第二条:对修改是关闭的。 同时,由于从抽象层导出一个或多个新的具体类来实现抽象类或者接口就可以改变系统的行为,因此系统的设计对扩展时开放的,这就满足了“开-闭”原则的第一条:对可变性的封装原则 。如何 设计好抽象层的类或者接口,我们必须对系统的可变性进行封装。这就是所谓的”对可变性的封装原则"(Principle of Encapsulation of Variation short for EVP)对可变性的封装原则 讲的是找到 一个系统的可变因素,将其封装起来。 “对可变性的封装原则”意味着两点: 1.一种可变性不应散落在很多角落,而应当被封装到一个对象里面。 2.一种可变性不应当与另一种可变性混合在一起。
posted @
2012-07-21 22:07 地心引力 阅读(703) |
评论 (0) |
编辑 收藏
今天和同学聊天,她像我描述了她最近的情况 ,一个字形容那就是"累" ---------身体累,心累,总之是各种累!!!
她说:“生活真的不容易,当初真的不该放下学业而去选择打工赚钱,结果是赔了夫人又折兵。聊天的过程中她一直在后悔自己的选择,生活的无奈,让她变得苍老了许多。。。。。聊着聊着就谈到了我,我在那一直抱怨,很希望自己能快点赚钱。她发来了一个很无奈的表情说:”要有长远的思想,不要像我一样“; 和她相比,我现在是很幸运,能在自己喜欢的领域学习知识,至少将来不会像她那样了,但心里总还是有那个别不过来的弯。看着其他同学假期赚钱,我心里也痒痒呢,不过反过来想想,其实我收获的比他们更多,我这个假期赚的财富比他们多少N倍了。只是现在还体现不出来吧!!!
有的时候很想给家里减轻点负担,赚点钱别自己的生活,但这似乎只能解决眼前的问题。从来没有为将来考虑过。从来没想过将来怎么办?现在暂时是赚到钱了,那以后呢,将来父母老了,我拿什么区孝敬父母?父母病了,需要大笔的医药费,去哪拿?这时候你在孝顺管用吗?没钱啥都白扯了!!!记得那次和米老师谈话,我就把我的这些想法说了出来,老师告诉我,这些困难都是暂时的,要想让家里人过好生活,那就得解决这种局面,眼前的小利益不能代表未来,那一刻我就告诉自己,我要改变这种态度,改变命运,作为学生我就要好好利用这个机会,用知识强大自己,虽然暂时打工能赚钱,我也要微微一笑略过!!!强大了以后会有大把大把的人民币或者是美元等着我呢。。。。。。。等父母老了,需要我的时候,我有能力去孝顺,而不是在那干掉眼泪,没办法。。。。。
李嘉诚的演讲中曾说道:”打工才是最愚蠢的投资“;也许很多人会认为打工是在赚钱。其实打工才是最大最愚蠢的投资。人生最宝贵的是什么?除了我们的青春还有什么更宝贵? 我们大多数人都抱怨穷,抱怨没钱想做生意又找不到资金。其实想来多么的可笑!其实我们自己就是一座金山(无形资产),只是自己不敢承认自己的能力。宁可埋起来也不敢利用(是金子总是会发光的)。宁可委委屈屈地帮人打工,把自己的资产双手拱让给了你的老板。
我们试想一下,有谁生下来上天就会送给他一大堆金钱的?有几个是含着金汤勺出生的呢?有谁是准备非常齐全了完美了再去创业就成功了?含着金汤匙出生的人毕竟是极少数、富不过三代,许多伟业都是平凡人创造出来的。计划永远赶不上变化,特别是在如今这个信息高度快速传播的年代!其实我们要想想为什么自己一直是打工仔?那是因为你安于现状!因为你没有勇气,你天生胆小怕事不敢另择它路!因为你没有勇往直前,没有超越自我的精神!虽然你曾想过改变自己的生活、改变自己穷困的命运、但是我们没有做,因为我们不敢做!我们害怕输,我们害怕输的一穷再穷!最后连想都不敢想了,觉得自己就算努力了、拼搏了、抱着雄心大志、结果还没看到预想的成就,也就放弃了。到最后我们就只能是一个打工仔!
天上永远不会掉馅饼,即使掉下来了,说不准会砸死你呢.生活的权利掌握在我们自己的手中,我们不要在走父母的老路了.从现在起不自卑,不退缩,敢作敢为,大胆前进,摆脱贫穷!!!做自己的老板
人、活着就要有一身价值……
posted @
2012-07-21 21:58 地心引力 阅读(807) |
评论 (1) |
编辑 收藏
首先我们了解一个名词ORM,全称是(Object Relational Mapping),即对象关系映射。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现,这样开发人员就可以把对数据库的操作转化为对这些对象的操作。Hibernate正是实现了这种思想,达到了方便开发人员以面向对象的思想来实现对数据库的操作。
Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java)、映射文件(*.hbm.xml)和数据库配置文件(*.properties/*.cfg.xml),它们各自的作用如下。
映射类(*.java):它是描述数据库表的结构,表中的字段在类中被描述成属性,将来就可以实现把表中的记录映射成为该类的对象了。
映射文件(*.hbm.xml):它是指定数据库表和映射类之间的关系,包括映射类和数据库表的对应关系、表字段和类属性类型的对应关系以及表字段和类属性名称的对应关系等。
数据库配置文件(*.properties/*.cfg.xml):它是指定与数据库连接时需要的连接信息,比如连接哪种数据库、登录数据库的用户名、登录密码以及连接字符串等。当然还可以把映射类的地址映射信息放在这里。
接下来让我们就一起走进Hibernate的七种映射关系:
1、单向一对一关联映射(one-to-one):
两个对象之间一对的关系,例如:Person(人)-IdCard(身份证)
有两种策略可以实现一对一的关联映射:
*主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系;数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联。如下图:
例子:单向一对一主键关联例子连接
*唯一外键关联:外键关联,本来是用于多对一的配置,但是加上唯一的限制之后(采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性为一),也可以用来表示一对一关联关系,其实它就是多对一的特殊情况。如下图:
例子:单向一对一唯一外键关联例子连接
注意:因为一对一的主键关联映射扩展性不好,当我们的需要发生改变想要将其变为一对多的时候变无法操作了,所以我们遇到一对一关联的时候经常会采用唯一外键关联来解决问题,而很少使用一对一主键关联。
2、单向多对一关联映射(many-to-one):
多对一关联映射原理:在多的一端加入一个外键,指向一的一端,如下图:
关键映射代码——在多的一端加入如下标签映射:
- <many-to-one name="group" column="groupid"/>
3、单向一对多关联映射(one-to-many):
一对多关联映射和多对一关联映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。如下图(学生和班级):
注意:它与多对一的区别是维护的关系不同
*多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来
*一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来
关键映射代码——在一的一端加入如下标签映射:
- <set name="students">
- <key column="classesid"/>
- <one-to-many class="com.hibernate.Student"/>
- </set>
缺陷:因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据,常用解决办法是改用双向关联映射,参见6。
4、单向多对多映射(many-to-many):
多对多关联映射新增加一张表才完成基本映射,如下图:
关键映射代码——可以在User的一端加入如下标签映射:
- <set name="roles" table="t_user_role">
- <key column="user_id"/>
- <many-to-many class="com.hibernate.Role" column="role_id"/>
- </set>
5、双向一对一关联映射:
对比单向一对一映射,需要在IdCard加入<one-to-one>标签,它不影响,只影响加载。如下图:
双向一对一主键映射关键映射代码——在IdCard端新加入如下标签映射:
- <one-to-one name="person"/>
双向一对一唯一外键映射关键映射代码——在IdCard端新加入如下标签映射:
- <one-to-one name="person"property-ref="idCard"/>
注意:一对一唯一外键关联双向采用<one-to-one>标签映射,必须指定<one-to-one>标签中的property-ref属性为关系字段的名称
6、双向一对多关联映射(非常重要):
采用一对多双向关联映射的目的主要是为了主要是为了解决一对多单向关联的缺陷而不是需求驱动的。
一对多双向关联的映射方式:
* 在一的一端的集合上采用<key>标签,在多的一端加入一个外键
* 在多的一端采用<many-to-one>标签
注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱
关键映射代码:
在Classes的一端加入如下标签映射:
- <set name="students"inverse="true">
- <key column="classesid"/>
- <one-to-many class="com.hibernate.Student"/>
- </set>
在Student的一端加入如下标签映射:
- <many-to-one name="classes" column="classesid"/>
注释:inverse属性
* inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效。
* inverse是控制方向上的反转,只影响存储
7、双向多对多关联映射:
双向的目的就是为了两端都能将对方加载上来,和单向多对多的区别就是双向需要在两端都加入标签映射,需要注意的是:
* 生成的中间表名称必须一样
* 生成的中间表中的字段必须一样
Role(角色)端关键映射代码:
- <set name="users" table="t_user_role">
- <key column="role_id"/>
- <many-to-many class="com.hibernate.User" column="user_id"/>
- lt;/set>
User(用户)端关键映射代码:
- <set name="roles" table="t_user_role">
- <key column="user_id"/>
- <many-to-many class="com. hibernate.Role" column="role_id"/>
- lt;/set>
总结:对于上面这七种关联映射中,最重要的就是一对多的映射,因为它更贴近我们的现实生活,比如:教室和学生就可以是典型的一对多的关系,而我们开发软件的目的之一就是为了解决一些生活中重复性问题,把那些重复的问题交给计算机帮助我们完成,从而来提高我们的工作效率。一句话:生活离开不开编程,编程更离不开生活。
posted @
2012-07-21 21:58 地心引力 阅读(820) |
评论 (1) |
编辑 收藏