首先上两个通用的图:
上面这两个图都是描述Ado.net的工作原理的。
应用程序读取数据共有三种方式:
(1)直接通过Command对象读取(但一次只能对一条数据,即表的一行),读完后不断开连接。
(2)通过DataReader对象读取(类似单向管道似的,一条一条的读数据),读完后不断开连接。
(3)通过DataAdapter一次读一堆数据(这个堆就是DataSet),读完后就断开数据库连接了。
应用程序更新和插入数据共有两种方式:
由于DataReader是单向的,所有不能用于插入和更新数据,只能从数据库读取数据,所以应用程序更新和插入数据只有上面的(1)和(3)两者方式。
从Ado.net的工作原理图可以看出,不管用哪种方式和数据库打交道,都必须有三个的东西:Connection,Command和Sql语句。
第(1)种方式如下图:
图中把工厂比喻成数据库,把商城仓库比喻成应用程序所在内存,把Command比喻成取货员“二愣子”(因为他比较笨),把Sql语句比喻成订单,把桥比喻成数据库连接对象。
第(1)方式的工作过程就是,首先要j架设好桥,然后二愣子拿到订单(Sql语句)后,就往工厂跑,把订单给工厂管理员,取回订单所需的货物(数据)后,再折返回来把货物放入仓库(内存)。但是由于一个人的力量有限,二愣子来回跑的过程中,一个来回只能搬回一件货物。这时候连接不能断(桥不能拆),因为每次需要取一件货物的时候,二愣子都需要来回跑。
方式(1)的总体印象就是,“二愣子”不断的来回跑。
第(2)种方式的工作过程就是,架设好桥后,二愣子拿着“订单”往工厂跑,但这次的订单比较复杂,他相当于一份合同,要求和工厂建立一个管道,仓库需要什么货物,直接操作管道的一头的控制按钮,则管道另一头会自动提取需要的货物并通过管道输送到仓库。这样“二愣子”就只需要跑一趟就行了(这份工作轻松、高兴!)。这时候连接也不能断(管道不能断),只有保持连接才能不断的一件件从工厂取货物并通过管道输送到仓库。
方式(2)的总体印象就是,有一天单向管道。
如下图:
第(3)种方式的工作过程就是,架设好桥后,二愣子拿着“订单”开着车往工厂跑,但这次订单要求的货物比较多,工厂就把这一堆货物帮二愣子装上车,二愣子高高兴兴的开着车兜着风把这一堆货物运回去。这次二愣子不仅能兜风,而且也只跑一趟(这份工作真拉风!)。车开回来后就可以断开连接了(完全可以把桥拆了),因为需要的所有货物都已经通过货车运回来了。此时,货车就比喻为DataAdapter对象,DataSet对象就比喻成货车拉回来的那“一堆货物的集合”。
方式(3)的总体印象就是,“二愣子”开着货车。
见下图:
另外,网上有一个更好看点的图(意义和上图一样),如下:
总结:从上面的图可以看出,无论用什么方式取货物都必须有三个东西参与才能完成:桥,二愣子,订单。即:Connection,Command和Sql语句。实际上在使用DataAdapter的时候可能看不到Command对象,其实DataAdapter也是必须通过Command对象取货物的,只不过DataAdapter内部自己有Command对象而已,DataAdapter使用自己内部的Command对象(这点从最上面的Ado.net原理图可以看出)。
取货物就是从数据库中取数据,更新和插入数据到数据库的过程和取数据一样,也需要Connection,Command和Sql语句这三个东西,此不赘述。
具体代码如下:
假设配置文件如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="Northwind" providerName ="System.Data.SqlClient" connectionString ="server=(local); integrated security = SSPI; database = Northwind" /> </connectionStrings> </configuration>
(1)直接通过Command对象读取(但一次只能对一条数据,即表的一行),读完后不断开连接。
第一步:建立Connection对象(桥)
string connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString(); //从配置文件中取出连接字符串
SqlConnection conn = new SqlConnection(connectionString); conn.Open(); //打开连接
第二步:建立SQL语句(订单)
string sqlStr=“ Select * from Student where ID='10' ”;
第三步:建立Command对象(二愣子),用这个对象直接返回一个行数据。
SQLCommand cmd=new SQLCommand(sqlStr,conn); //参数就是sql语句和连接对象
//注意通过new Command对象的连个参数把这三个必须的东西联系在一起了。
下面就是执行Command对象的方法了,共有三种方法:
int LineCount=cmd.ExecuteNonQuery(); //一般用于更新和插入语句,不返回查询结果,但这个函数的返回值本身返回影响的行数。
DataReader dr=cmd.ExecuteReader(); //一般用于Select语句返回查询的数据,然后通过DataReader一个个的读取。
int OneValue=cmd.ExecuteScaler(); //一般用于Select查询,但返回结果为一个值的情况,比如SQL语法中的Count函数和Sum函数。这也印证了二愣子力量有限,仅凭自己的力量一次只能搬回一件货物,或者不搬回货物,仅通知数据库更新和插入一个数据。
总之,更新和插入用ExecuteNonQuery,查询主要使用ExecuteReader,特殊情况(只返回单个值)才用ExecuteScaler。
最后别忘了关闭连接,conn.Close();
(2)通过DataReader对象读取(类似单向管道似的,一条一条的读数据),读完后不断开连接。
第一步:建立Connection对象(桥)
string myconn="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind";
SqlConnection conn=new SqlConnection(myconn);
第二步:建立SQL语句(订单)
string mysql="select OrderID,CustomerID from Orders where CustomerID='CHOPS'";
第三步:建立Command对象(二愣子),但用这个对象返回一个管道DataReader
SqlCommand cmd=new(mysql,conn); conn.Open(); //打开数据库连接,用之前打开就行,放在哪无所谓
//通过SqlCommand的ExecuteReader()方法构造DataReader 对象。
SqlDataReader myreader=cmd.ExecuteReader();
while(myreader.read()){
Console.WriteLine(myreader.GetInt32(0)+","+myreader.GetString(1));
}
myreader.Close();
myconnection.Close();
补充:SqlDataReader读数据方法有两大类,带小括号的函数和带中括号的索引属性
带小括号的有,GetInt32(), GetString()等,参数都是int类型,表示列号,也只能使用列号。
带中括号的有,直接带上中括号,有myreader[0] 和 myreader["ID"]两种,即可以使用列号,也可以使用列名。
(3)通过DataAdapter一次读一堆数据(这个堆就是DataSet),读完后就断开数据库连接了。
第一步:建立Connection对象(桥)
string connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString(); //从配置文件中取出连接字符串
SqlConnection conn = new SqlConnection(connectionString); conn.Open(); //打开连接
第二步:建立SQL语句(订单)
string sqlStr=“
1.1 JMS
JMS(Java Messaging Service)是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,中文称Java消息服务。JMS是一种与厂商无关的 API,用来访问消息收发系统消息;就像JDBC(Java Database Connectivity)可以用来访问许多不同关系数据库一样,JMS则提供同样与厂商无关的访问方法,以访问消息收发服务。
JMS是在Java标准化组织(JCP)内开发的标准(代号JSR 914)。2001年6月25日,发布了JMS 1.0.2b,2002年3月18日发布了JMS1.1,统一了消息域。
JMS规范约定了两种消息方式:P2P(Point To Point)和发布/订阅(Publish/Subscribe)。P2P是用来进行两个节点之间的点对点通信;发布/订阅则是用于一个发布者和多个订阅者之间的通信。
1.2 MQ
MQ是Message Queue的缩写,中文称消息队列,MQ是在消息的传输过程中保存消息的容器。消息管理器在将消息从它的源中继到它的目标时充当中间人;队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。
MQ有很多不同厂商和语言实现的产品,如Sun MQ、Microsoft MQ、IBM MQ的等商业产品;Java语言实现的MQ,则有ActiveMQ、基于JMS标准的OpenJMS,以及新近的迁移项目Jafka等开源项目。
1.3 二者关系
JMS是一个用于提供消息服务的技术规范,TA制定了在整个消息服务提供过程中的所有数据结构和交互流程。而MQ则是消息队列服务,是面向消息中间件(MOM)的最终实现,是真正的服务提供者;MQ的实现可以基于JMS,也可以基于其他规范或标准。
2 MQ产品介绍
2.1 ActiveMQActiveMQ是Apache的一个顶级Java开源项目,也是目前最流行的,能力强劲的开源消息队列。ActiveMQ是比较老牌的MQ,2004年由Apache开源孵化,2007年成为Apache顶级项目。最新版本已经更新到5.8.0,TA拥有众多特性:
支持Java,C/C++,C#,Ruby,Perl,Python,PHP等多种语言实现客户端和协议。
完全支持企业集成模式。
支持消息分组、虚拟目标及复合目标等高级特性。
完全支持JMS1.1,和J2EE1.4(持久化、事务,及XA消息)。
提供对Spring的支持,可以很容易内嵌到使用Spring的系统中。
通过了常规的J2EE服务器(如TomEE、Geronimo、Jboss、GlassFish、WebLogic等)的测试。
支持多种传输协议,如:in-VM、TCP、SSL、NIO、UDP、multicast、Jgroups、JXTA等。
支持通过JDBC和journal提供高速的消息持久化。
从设计上保证了高性能的集群、客户端-服务器、点对点通信。
支持基于Web的API及其他方式的REST调用。
支持Ajax。
支持CXF和Axis。
支持用作内嵌JMS provider,进行测试。
2.2 其他产品
2.2.1 OpenJMS
OpenJMS是完全基于JMS1.1规范实现的JMS provider,有以下特性:
支持通过JDBC提供消息持久化。
支持Applet。
能够与Jakarta Tomcat这样的Servlet容器结合。
支持RMI、TCP、HTTP与SSL协议。
提供可靠消息传输、事务和消息过滤。
2.2.2 Jafka
基于scala语言开发的分布式发布订阅消息系统Kafka的Java移植版,功能比较简单,但其最大的特色分布式和高性能:
消息持久化非常快,服务端存储消息的开销为O(1)。
基于文件系统,能够持久化TB级的消息而不损失性能。
吞吐量很大,同等机器配置下,Jafka吞吐量比同类MQ均高。
完全的分布式系统,broker、producer、consumer都原生自动支持分布式;自动实现复杂均衡。
内核非常小,内部机制简洁,适合进行内嵌或者二次开发。
消息格式以及通信机制非常简单,适合进行跨语言开发。
3 ActiveMQ的使用
ActiveMQ的使用分为两种,一种是嵌入式,即把ActiveMQ作为内嵌的JMS provider集成到Tomcat或其他Web服务器中;另一种是独立部署,即ActiveMQ单独部署,独立运行,通过ActiveMQ提供的API进行进程外访问。我们采用独立部署的方式使用ActiveMQ,这样的做法更有利于业务的解耦和工程部署结构的分离;也有利于对ActiveMQ进行配置定制和优化。
我们知道JMS规范中约定了两种消息发送方式:P2P和Publish/Subscribe。根据业务的需求,我们采用P/S方式更为合理,也能更好的发挥ActiveMQ本身的优势。
3.1 消息的发布
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Topic topic = session.createTopic("myTopic.messages");
MessageProducer producer = session.createProducer(topic);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
while(true) {
TextMessage message = session.createTextMessage();
message.setText("TIME:" + (new Date()).toLocaleString());
// 发布主题消息
producer.send(message);
System.out.println("Sent message: " + message.getText());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3.2 消息的订阅
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Topic topic = session.createTopic("myTopic.messages");
// 创建订阅
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("Received message: " + tm.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
3.3 消息的持久订阅
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
String ip = "";
try {
// 获取本机IP
InetAddress addr = InetAddress.getLocalHost();
ip = addr.getHostAddress().toString();
} catch (UnknownHostException ex) {
ex.printStackTrace();
ip = "";
}
if(!"".equals(ip)) {
System.out.println("CLIENT: " + ip);
// 设置订阅客户端ID
connection.setClientID(ip);
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
1. install the VMware ESXi v5.1.0 on the host (USB or DVD or via network)
2. install the client in personal desktop
3. create VM and install client OS(RHEL 6)
4. install the VMware TOOLs in the client OS - RHEL( VM->guest->install/upgrade VMware TOOLS; mount ISO and install the tools)
5. ENABLE the ESX shells and SSH to the host
6. enable SRIOV via ESXCLI, and configure PCI devices
ref:
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2038739