1705-XML約束及反射


XML

XML:eXtends MarkUp Language≡迹可拓展的標(biāo)記語言睦霎。是可以用戶自定標(biāo)簽的,本身沒有語法約束;
功能: 配置文件
文檔聲明(必須寫在xml第一行):<?xml version = "1.0" encoding = "UTF-8"?>

約束就是xml的書寫規(guī)則
常用方法:引用外部約束文件走诞,編寫XML約束實例文檔


XML約束_DTD

內(nèi)部約束:在XML內(nèi)部定義DTD
外部約束:在外部文件中定義dtd
    本地dtd文件約束:<! DOCTYPE Students SYSTEM "Student.dtd">
    網(wǎng)絡(luò)dtd文件約束:<! DOCTYPE Students PUBLIC "名稱空間" "Student.dtd">

XML約束_schema

導(dǎo)入xsd約束文檔:
        1副女、編寫根標(biāo)簽
        2、引入實例名稱空間 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        3速梗、引入名稱空間 xsi:schemaLocation="http://www.itcast.cn/xml student.xsd"    
        4肮塞、引入默認(rèn)的名稱空間

常用XML約束

//web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

//struts.xml
<!DOCTYPE struts PUBLIC 
     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 
     "http://struts.apache.org/dtds/struts-2.3.dtd">
//validation.xml 
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> 

//hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
//hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

//Spring - applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"   
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"      xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans.xsd    
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop.xsd    
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx.xsd    
    http://www.springframework.org/schema/context    
    http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

//ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

DTD的約束

     * 快速入門
     * 快速入門的步驟:
         * 需要出現(xiàn)哪些標(biāo)簽襟齿?
         * 在DTD的文件中編寫元素
             <!ELEMENT 元素名稱 元素類型>
         * 判斷元素是否是復(fù)雜還是簡單元素姻锁?
             * 如果是簡單元素:(#PCDATA)    代表是字符串
             * 如果是復(fù)雜元素:(子節(jié)點)

         * 需要在xml引入DTD的文件
             * <!DOCTYPE 根節(jié)點 SYSTEM "DTD文件的地址">

     * DTD與XML文檔的關(guān)聯(lián)方式
         * 可以在XML的文件中直接書寫DTD的代碼。(**經(jīng)常使用**)
             <!DOCTYPE 根節(jié)點 [
                 DTD的代碼
             ]>

         * 引入本地的DTD文件(經(jīng)常使用)
             <!DOCTYPE 根節(jié)點 SYSTEM "DTD文件的地址">

         * 引入網(wǎng)絡(luò)上的DTD文件
             <!DOCTYPE 根節(jié)點 PUBLIC "DTD文件名稱" "DTD文件的地址">

Schema(.xsd)約束

兩者區(qū)別:后綴名.xsd猜欺,Schema更新數(shù)據(jù)更加完善位隶,支持命名空間,DTD的替代者开皿。
什么是命名空間:當(dāng)文件當(dāng)如多個約束文件時涧黄,且有相同標(biāo)簽名時,無法區(qū)分赋荆,類似java中Date類笋妥,sql和util下都有Date.

XML解析

常用的有兩種DOM和SAX 解析方式
          * 區(qū)別:
              DOM解析XML
                * 在內(nèi)存中形成樹狀結(jié)構(gòu)
                * 缺點:如果文檔過大,容易產(chǎn)生內(nèi)存溢出的問題窄潭。  
                * 優(yōu)點:方便做增刪改的操作    

              SAX解析
                * 基于事件驅(qū)動春宣,邊讀邊解析
                * 優(yōu)點:不會產(chǎn)生內(nèi)存溢出問題。
                * 缺點:不能做增刪改操作嫉你。(DOM4J在內(nèi)存生成樹狀結(jié)構(gòu))

      *月帝,只能使用DOM方式,因為SAX只能做查詢幽污。
      * DOM4J 和JAXP 屬于XML解析開發(fā)包           
            DOM4J:
            *全世界都在用嚷辅,開源開發(fā)包
          *  企業(yè)都在用DOM4J
          * 全部都可以做。

1.DOM4J的解析(必須會距误,企業(yè)中用的多)

    1.先下載DOM4J相應(yīng)的jar包簸搞。導(dǎo)入工程中,才能使用准潭。
    2.把dom4j-1.6.1.jar導(dǎo)入到工程中趁俊。
    3.WEB項目:復(fù)制dom4j-1.6.1.jar到    WebRoot -- WEB-INF -- lib里面。就ok惋鹅。
* DOM4J對XPATH的支持
    * 導(dǎo)入包则酝。jaxen-1.1-beta-6.jar。
    * 怎么使用?
        selectNodes("/AAA")            返回集合
        selectSingleNode()        一個Node對象

    * 參數(shù)就是xpath的語法
        * /AAA/BBB            獲取BBB的節(jié)點
        * //BBB                無論層級關(guān)系沽讹,找到BBB的節(jié)點
        * *                    代表是所有
        * /AAA/BBB[1]        找到BBB的第一個        /AAA/BBB[last()]    最后一個
        * @                    屬性

DOM4J擴展:
通過XML管理學(xué)生的信息般卑。
可以在項目下建立一個xml用于存放學(xué)生信息,建一個學(xué)生類爽雄,操作類(用于對xml操作增刪改查)蝠检,測試類。

使用dom4j之前挚瘟,必須要導(dǎo)入相應(yīng)的jar包:必須使用SaxReader加載xml文檔獲得Document叹谁,通過Document獲取根元素,然后就可以進(jìn)行相關(guān)操作:
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

public class TestDom4j {
    @Test
    public void testReadWebXML() {
        try {
            // 1.獲取解析器
            SAXReader saxReader = new SAXReader();
            // 2.獲得document文檔對象
            Document doc = saxReader.read("web.xml");
            // 3.獲取根元素
            Element rootElement = doc.getRootElement();
            // System.out.println(rootElement.getName());//獲取根元素的名稱
            // System.out.println(rootElement.attributeValue("version"));//獲取根元素中的屬性值
            // 4.獲取根元素下的子元素
            List<Element> childElements = rootElement.elements();
            // 5.遍歷子元素
            for (Element element : childElements) {
                //6.判斷元素名稱為servlet的元素
                if ("servlet".equals(element.getName())) {
                    //7.獲取servlet-name元素
                    Element servletName = element.element("servlet-name");
                    //8.獲取servlet-class元素
                    Element servletClass = element.element("servlet-class");
                    System.out.println(servletName.getText());
                    System.out.println(servletClass.getText());
                }
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
2.JAXP的SAX解析乘盖,只能做查詢焰檩,不能做增刪改。
* SAX解析(原始代碼)
          * 解析器
              //獲取解析器的工廠
SAXParserFactory factory = SAXParserFactory.newInstance();
              //獲取解析器對象
SAXParser sp = factory.newSAXParser();
             // 解析XML(XML的文件的地址订框,事件處理器)
sp.parser(User.xml,new MyHander());

獲取節(jié)點等去看jdk開發(fā)文檔析苫。
        * DOM(原始代碼)
            * DocumentBuilderFactory    :解析器工廠類
            * DocumentBuilder    獲取解析器對象
JAXP解析
            * 解析XML(Document parse(String uri) )
                // 獲取解析器工廠類
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                // 獲取解析器對象
                DocumentBuilder builder = factory.newDocumentBuilder();
                // 解析XML的文檔,返回document對象
                Document document = builder.parse("src/book2.xml");
        * 回寫
            * 獲取回寫的工廠類
            * 獲取回寫對象
            * 調(diào)用回寫的方法進(jìn)行回寫穿扳。
                // 創(chuàng)建回寫類的工廠
                TransformerFactory transformerFactory =  TransformerFactory.newInstance();
                // 獲取回寫類
                Transformer transformer = transformerFactory.newTransformer();
                // 調(diào)用回寫的方法
                transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml"));
 

2 .反射

1衩侥、Java反射機制(Java-Reflect):
在運行狀態(tài)中殴蓬,對于任意一個類仅讽,都能夠知道這個類中的所有屬性和方法;對于任意一個對象狈癞,都能夠調(diào)用它的任意一個方法和屬性履羞;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java的反射機制峦萎。
反射是Java開發(fā)中一個非常重要的概念,掌握了反射的知識吧雹,才能更好的學(xué)習(xí)Java高級課程.

總之骨杂,通過反射可以對類的變量,構(gòu)造方法雄卷,成員方法進(jìn)行操作搓蚪。

2、Java 反射機制的功能
在運行時判斷任意一個對象所屬的類丁鹉。
在運行時構(gòu)造任意一個類的對象妒潭。
在運行時判斷任意一個類所具有的成員變量和方法。
在運行時調(diào)用任意一個對象的方法揣钦。
生成動態(tài)代理雳灾。


獲取class對象的三種方式


獲取Class對象的方式一:
通過對象具備的getClass方法(源于Object類的方法)。有點不方便冯凹,需要用到該類谎亩,并創(chuàng)建該類的對象,再調(diào)用getClass方法完成。
Person p = new Person();//創(chuàng)建Peron對象
Class clazz = p.getClass();//通過object繼承來的方法(getClass)獲取Person對應(yīng)的字節(jié)碼文件對象

獲取Class對象的方式二:
        每一個類型都具備一個class靜態(tài)屬性匈庭,通過該屬性即可獲取該類的字節(jié)碼文件對象夫凸。比第一種簡單了一些,僅用一個靜態(tài)屬性就搞定了阱持。但是夭拌,還是有一點不方便,還必須要使用到該類衷咽。
Class clazz = Person.class;

#獲取Class對象方式三(常用):
         * 去找找Class類中是否有提供獲取的方法呢鸽扁?
         * 找到了,static Class forName(className);
         * 相對方便的多镶骗,不需要直接使用具體的類桶现,只要知道該類的名字即可。
         * 而名字完成可以作為參數(shù)進(jìn)行傳遞 ,這樣就可以提高擴展性卖词。
         * 所以為了動態(tài)獲取一個類巩那,第三種方式最為常用吏夯。 
    Class clazz = Class.forName("com.it.Reflect.Person");//必須類全名

創(chuàng)建Person對象的方式
以前:1此蜈,先加載com.it.Reflect.Person類進(jìn)內(nèi)存。
2,將該類封裝成Class對象噪生。 
        3,根據(jù)Class對象裆赵,用new操作符創(chuàng)建com.it.Reflect.Person對象。
    4,調(diào)用構(gòu)造函數(shù)對該對象進(jìn)行初始化跺嗽。 
com.it.Reflect.Personp = new com.it.Reflect.Person();

通過方式三:(此外還可以使用構(gòu)造战授,構(gòu)造可以指定參數(shù)---如String.class)
String className = "com.it.Reflect.Person";
//1,根據(jù)名稱獲取其對應(yīng)的字節(jié)碼文件對象
        1桨嫁,通過forName()根據(jù)指定的類名稱去查找對應(yīng)的字節(jié)碼文件植兰,并加載進(jìn)內(nèi)存。
        2璃吧,并將該字節(jié)碼文件封裝成了Class對象楣导。
        3,直接通過newIntstance方法畜挨,完成該對象的創(chuàng)建筒繁。
        4,newInstance方法調(diào)用就是該類中的空參數(shù)構(gòu)造函數(shù)完成對象的初始化巴元。 
Class clazz = Class.forName(className);
//2毡咏,通過Class的方法完成該指定類的對象創(chuàng)建。
Object object = clazz.newInstance();//該方法用的是指定類中默認(rèn)的空參數(shù)構(gòu)造函數(shù)完成的初始化逮刨。 

#清單1呕缭,獲取字節(jié)碼文件中的字段。
Class clazz = Class.forName("new com.it.Reflect.Person");
//獲取該類中的指定字段。比如age
Field field = clazz.getDeclaredField("age");
//clazz.getField("age");    
//為了對該字段進(jìn)行操作恢总,必須要先有指定類的對象落恼。
Object obj = clazz.newInstance();
//對私有訪問,必須取消對其的訪問控制檢查离熏,使用AccessibleObject父類中的setAccessible的方法
field.setAccessible(true);//暴力訪問佳谦。建議大家盡量不要訪問私有   
field.set(obj, 789);
//獲取該字段的值。
Object o = field.get(obj);
System.out.println(o);
備注:getDeclaredField:獲取所有屬性滋戳,包括私有钻蔑。
getField:獲取公開屬性,包括從父類繼承過來的奸鸯,不包括非公開方法咪笑。

#清單2,獲取字節(jié)碼文件中的方法娄涩。
//根據(jù)名稱獲取其對應(yīng)的字節(jié)碼文件對象
Class clazz = Class.forName("new com.it.Reflect.Person");
//調(diào)用字節(jié)碼文件對象的方法getMethod獲取class對象所表示的類的
公共成員方法(指定方法)窗怒,參數(shù)為方法名和當(dāng)前方法的參數(shù),無需創(chuàng)
建對象蓄拣,它是靜態(tài)方法
Method method = clazz.getMethod("staticShow", null);
//調(diào)用class對象所表示的類的公共成員方法扬虚,需要指定對象和方法中
的參數(shù)列表
method.invoke(null, null);
 
Class clazz = Class.forName("new com.it.Reflect.Person");   
    //獲取指定方法。
Method method = clazz.getMethod("publicShow", null);
    //獲取指定的類對象球恤。 
Object obj = clazz.newInstance();
method.invoke(obj, null);//對哪個對象調(diào)用方法辜昵,是參數(shù)組
好處:大大的提高了程序的擴展性。

3咽斧、Java 反射機制的應(yīng)用場景
逆向代碼 堪置,例如反編譯
與注解相結(jié)合的框架 例如Retrofit
單純的反射機制應(yīng)用框架 例如EventBus
動態(tài)生成類框架 例如Gson


使用反射生成并操作對象

Class 對象可以獲得該類里的方法(由 Method 對象表示)、構(gòu)造器(由 Constructor 對象表示)张惹、成員變量(由 Field 對象表示)舀锨,這三個類都位于 java.lang.reflect 包下。
程序可以通過 Method 對象來執(zhí)行對應(yīng)的方法宛逗,
通過 Constructor 對象來調(diào)用對應(yīng)的構(gòu)造器創(chuàng)建實例坎匿,
通過 Field 對象直接訪問并修改對象的成員變量值。
1、創(chuàng)建對象
通過反射來生成對象的兩種方式:
使用 Class 對象的 newInstance() 方法來創(chuàng)建該 Class 對象對應(yīng)類的實例格嗅。
要求:Class 對象的對應(yīng)類要有默認(rèn)構(gòu)造器襟衰,而執(zhí)行 newInstance() 方法實際上是利用默認(rèn)構(gòu)造器來創(chuàng)建該類的實例。
先使用 Class 對象獲取指定的 Constructor 對象,再調(diào)用 Constructor 對象的 newInstance() 方法來創(chuàng)建該 Class 對象對應(yīng)類的實例把介。
這種方式可以選擇使用指定的構(gòu)造器來創(chuàng)建實例。
通過第一種方式來創(chuàng)建對象是比較常見的情形,在很多的 JavaEE 框架中都需要根據(jù)配置文件信息來創(chuàng)建Java對象。從配置文件中讀取的只是某個類的字符串類名,程序需要根據(jù)該字符串來創(chuàng)建對應(yīng)的實例眨唬,就必須使用到反射。

這種使用配置文件來配置對象临庇,然后由程序根據(jù)配置文件來創(chuàng)建對象的方式非常有用,如 Spring 框架就采用這種方式大大簡化了 JavaEE 應(yīng)用的開發(fā),當(dāng)然,Spring采用的是 XML 配置文件——因為 XML 配置文件能配置的信息更加的豐富闺魏。


第二種方式,利用指定的構(gòu)造器來創(chuàng)建 Java 對象司草。
獲取該類的 Class 對象泡仗。
利用 Class 對象的 getConstrustor() 方法來獲取指定的構(gòu)造器埋虹。
調(diào)用 Construstor 的 newInstance() 方法來創(chuàng)建 Java 對象娩怎。

1.獲取該類的 Class 對象爬泥。
2.利用 Class 對象的 getConstrustor() 方法來獲取指定的構(gòu)造器境输。
3.調(diào)用 Construstor 的 newInstance() 方法來創(chuàng)建 Java 對象。

設(shè)計模式

目前已學(xué)已講的設(shè)計模式:
1,裝飾 : 在不必改變原類文件和使用繼承的情況下颖系,動態(tài)地擴展一個對象的功能嗅剖。典型就是JavaIO框架。
2,單例 : 一個類有且僅有一個實例嘁扼,并且自行實例化向整個系統(tǒng)提供信粮。
3,簡單工廠 : 專門生產(chǎn)勢力的類,把類的實例過程抽取到一個專門的類里偷拔。
4,工廠方法 : 創(chuàng)建一個工廠接口和創(chuàng)建多個工廠實現(xiàn)類蒋院,這樣一旦需要增加新的功能亏钩,直接增加新的工廠類就可以了
5,適配器 : 將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口。典型就是GUI里各種事件的處理欺旧。
6,模版 : 定義一個操作中的算法的骨架,而將步驟延遲到子類中姑丑。
7,動態(tài)代理 : 在實現(xiàn)階段不用關(guān)心代理類,而在運行階段才指定哪一個對象辞友。
總體來說設(shè)計模式分為三大類:
創(chuàng)建型模式栅哀,共五種:工廠方法模式、抽象工廠模式留拾、單例模式疫向、建造者模式、原型模式。
結(jié)構(gòu)型模式,共七種:適配器模式焊刹、裝飾器模式虐块、代理模式、外觀模式儡率、橋接模式、組合模式浪汪、享元模式。
行為型模式,共十一種:策略模式、模板方法模式踏幻、觀察者模式该面、迭代子模式、責(zé)任鏈模式隔缀、命令模式题造、備忘錄模式、狀態(tài)模式揽思、訪問者模式鲤屡、中介者模式、解釋器模式福侈。

3 .利用反射實現(xiàn)自定義DBUtils

目的:執(zhí)行sql語句酒来,得到結(jié)果并封裝數(shù)據(jù)
在這里用反射模擬DBUtils框架的query()方法:
DBUtils查詢結(jié)果為單個數(shù)據(jù)
DBUtils查詢結(jié)果為單行數(shù)據(jù)
DBUtils查詢結(jié)果為多行數(shù)據(jù)
準(zhǔn)備工作:
數(shù)據(jù)庫驅(qū)動jar包,C3P0jar包癌刽,C3P0配置文件xml
使用用配置文件編寫C3P0工具類役首,工具類提供獲取連接,連接池及釋放資源的方法
編寫要封裝成的bean類显拜,提供的變量名和查詢的數(shù)據(jù)列名一致衡奥,提供setXxx()方法
使用C3P0工具類和bean類編寫MyDBUtils

編寫C3P0工具類:

提供getConnection(),getDataSource(),release()方法
    public class C3P0Utils {
        // 創(chuàng)建連接池,以默認(rèn)方式加載配置文件(必須在src包下以c3p0-config.xml命名)
        private static DataSource ds = new ComboPooledDataSource();

        // 提供獲得連接池的方法
        public static DataSource getDataSource() {
            return ds;
        }

        // 提供獲得連接的方法
        public static Connection getConnection() {
            Connection connection = null;
            try {
                connection = ds.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }

        // 提供釋放資源的方法
        public static void release(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

編寫bean類:

提供的變量名和查詢的數(shù)據(jù)列名一致,提供setXxx()方法能夠進(jìn)行數(shù)據(jù)存儲

    public class User{
        private int sid;
        private String name;
        private int age;
        private String sex;
        private double price;
        private int type;

        public int getSid() {
            return sid;
        }
        public void setSid(int sid) {
            this.sid = sid;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
        public int getType() {
            return type;
        }
        public void setType(int type) {
            this.type = type;
        }
        @Override
        public String toString() {
            return "User [sid=" + sid + ", name=" + name + ", age=" + age + ", sex=" + sex + ", price=" + price + ", type="
                    + type + "]";
        }
    }

使用工具類和bean類編寫DBUtils類:

ResultSetMetaData getMetaData():可以獲得ResultSet的所有列名
因為 PreparedStatement 對象被預(yù)編譯远荠,所以不必執(zhí)行就可以知道它將返方法矮固,而不必等待執(zhí)行該對象,然后再對返回的 ResultSet 對象調(diào)用
ResultSetMetaData metaData = preparedStatement.getMetaData();
ResultSetMetaData getMetaData():
可以獲得ResultSet的所有列名
獲取此 ResultSet 對象的列的編號譬淳、類型和屬性档址。
ResultSetMetaData metaData = resultSet.getMetaData();
String getColumnName(int column):獲取指定列的名稱。
int getColumnCount():返回此 ResultSet 對象中的列數(shù)邻梆。
for (int i = 0; i < metaData.getColumnCount(); i++) {
String columnName = metaData.getColumnName(i + 1);// 列從第一行開始守伸,獲得每一行的列名
Object object = resultSet.getObject(columnName);// 獲得每一行數(shù)據(jù)中每一列的數(shù)據(jù)
}

遇到的問題:

判斷方法名與set+metaData.getColumnName()后,在設(shè)置值時浦妄,price在數(shù)據(jù)庫中類型為double尼摹,而我在編寫bean類時設(shè)置的是int類型,因此中途發(fā)生了bug剂娄。因此一定要注意列名和方法名的類型和名字必須要一模一樣

代碼實現(xiàn):

    public class MyDBUtils {
        /**
         * 模擬DBUtils的query()方法的三種結(jié)果集封裝方法: A:ScalarHandler處理單個數(shù)據(jù) B:BeanHandler處理單行數(shù)據(jù)
         * C:BeanListHandler處理多行數(shù)據(jù)
         * 
         * @param <T>
         * @throws Exception
         */

        // 封裝單行數(shù)據(jù)
        public <T> Object queryScalarHandler(DataSource ds, String sql, Class<T> clazz, Object[] params) throws Exception {
            // 1:加載驅(qū)動
            // 2:獲得連接
            Connection connection = ds.getConnection();
            // 3:獲得執(zhí)行sql語句對象
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                preparedStatement.setObject(i + 1, params[i]);// 設(shè)置占位符的值
            }

            // 如何取得列名?ResultSetMetaData getMetaData():獲取此 ResultSet 對象的列的編號蠢涝、類型和屬性。
            // ResultSetMetaData metaData = resultSet.getMetaData();
            ResultSetMetaData metaData = preparedStatement.getMetaData();

            // 4:執(zhí)行sql語句阅懦,獲得結(jié)果集
            ResultSet resultSet = preparedStatement.executeQuery();
            // 5:處理結(jié)果集
            // 這里將得到的數(shù)據(jù)設(shè)置到clazz的對應(yīng)值中輸出

            // 獲取給定bean類的實例對象
            T t = null;
            Method[] methods = clazz.getDeclaredMethods();// 獲得bean類的所有方法
            while (resultSet.next()) {
                t = clazz.newInstance();

                // String getColumnName(int column):獲取指定列的名稱和二。
                // int getColumnCount():返回此 ResultSet 對象中的列數(shù)。
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnName(i + 1);// 列從第一行開始耳胎,獲得每一行的列名
                    Object object = resultSet.getObject(columnName);// 獲得每一行數(shù)據(jù)中每一列的數(shù)據(jù)
                    // 將得到的每一個數(shù)據(jù)賦給bean類中的成員變量
                    for (Method method : methods) {
                        if (method.getName().equalsIgnoreCase("set" + columnName)) {// 如果bean類的方法名和set+列名相同
                            method.invoke(t, object);// bean類成員變量賦值
                        }
                    }
                }
            }
            // 6:釋放資源
            C3P0Utils.release(resultSet, preparedStatement, connection);
            return t;
        }

        // 封裝多行數(shù)據(jù)惯吕,并封裝成List<E>
        public <E> List<E> queryBeanListHandler(DataSource ds, String sql, Class<E> clazz, Object[] params)
                throws Exception {
            // 1:注冊驅(qū)動
            // 2:獲得連接
            Connection connection = ds.getConnection();
            // 3:獲得執(zhí)行sql語句的對象
            PreparedStatement prepareStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                prepareStatement.setObject(i + 1, params[i]);// 設(shè)置占位符
            }
            // 獲取所有列名
            ResultSetMetaData metaData = prepareStatement.getMetaData();

            // 4:執(zhí)行sql語句
            ResultSet resultSet = prepareStatement.executeQuery();

            // 獲取bean類中的所有方法
            Method[] methods = clazz.getMethods();
            // 5:處理結(jié)果集
            List<E> list = new ArrayList<>();
            while (resultSet.next()) {
                // 獲取每一列的數(shù)據(jù)賦值給bean的實體對象
                E e = clazz.newInstance();

                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    // 獲得每一列的當(dāng)前列名
                    String columnName = metaData.getColumnName(i + 1);
                    Object object = resultSet.getObject(columnName);// 得到了每一列的數(shù)據(jù)
                    // 將每一列的數(shù)據(jù)賦值到bean類實體對象
                    // 遍歷方法Method數(shù)組
                    for (Method method : methods) {
                        if (method.getName().equalsIgnoreCase("set" + columnName)) {
                            method.invoke(e, object);
                        }
                    }
                }
                list.add(e);
            }
            // 6:釋放資源
            C3P0Utils.release(resultSet, prepareStatement, connection);

            return list;
        }

        // 查詢單個數(shù)據(jù)
        public Object querySigle(DataSource ds, String sql, Object[] params) throws Exception {
            // 1:注冊驅(qū)動
            // 2:獲得連接
            Connection connection = ds.getConnection();
            // 3:創(chuàng)建執(zhí)行sql語句的對象
            PreparedStatement prepareStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                prepareStatement.setObject(i + 1, params[i]);// 設(shè)置占位符
            }
            // 4:執(zhí)行sql語句
            ResultSet resultSet = prepareStatement.executeQuery();
            // 5:處理結(jié)果
            Object object = null;
            while (resultSet.next()) {
                object = resultSet.getObject(1);// 獲取到得到的數(shù)據(jù)
            }
            // 5:釋放資源
            C3P0Utils.release(resultSet, prepareStatement, connection);
            return object;
        }
    }

測試:

    public class MyDBUtilsTest {

        //測試單行數(shù)據(jù):獲取user表中sid為1的明星信息
        @Test
        public void test01() throws Exception {
            MyDBUtils md = new MyDBUtils();
            String sql = "select * from user where sid=?";
            Object[] params = {1};

            Object object = md.queryScalarHandler(C3P0Utils.getDataSource(), sql, User.class, params);
            System.out.println(object);
        }

        //測試多行數(shù)據(jù):獲取user表的所有明星信息
        @Test
        public void test02() throws Exception {
            String sql = "select * from user";

            MyDBUtils md = new MyDBUtils();
            Object[] params = {};
            List<User> list = md.queryBeanListHandler(C3P0Utils.getDataSource(), sql, User.class, params);
            System.out.println(list);
        }

        //測試多行數(shù)據(jù):統(tǒng)計type為3的明星人數(shù)
        @Test
        public void test03() throws Exception {
            MyDBUtils md = new MyDBUtils();
            String sql = "select count(*) from user where type=?";

            Object[] params = {3};
            Object object = md.querySigle(C3P0Utils.getDataSource(), sql, params);
            System.out.println(object);
        }
    }

測試結(jié)果:

獲得單行數(shù)據(jù)
user[sid=1, name=霆鋒, age=38, sex=male, price=10000.0, type=1]


獲得多行數(shù)據(jù)
* [user[sid=1, name=霆鋒, age=38, sex=male, price=10000.0, type=1],
* user[sid=2, name=寶寶, age=35, sex=male, price=2000.0, type=1],
* user[sid=3, name=羽凡, age=45, sex=male, price=3000.0, type=1],
* user[sid=5, name=小白, age=30, sex=female, price=8000.0, type=2],
* user[sid=6, name=房祖名, age=29, sex=male, price=8000.0, type=3],
* user[sid=7, name=柯震東, age=28, sex=male, price=500.0, type=3],


獲得單個數(shù)據(jù) 2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市怕午,隨后出現(xiàn)的幾起案子混埠,更是在濱河造成了極大的恐慌,老刑警劉巖诗轻,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揭北,居然都是意外死亡扳炬,警方通過查閱死者的電腦和手機吏颖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恨樟,“玉大人半醉,你說我怎么就攤上這事∪笆酰” “怎么了缩多?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長养晋。 經(jīng)常有香客問我衬吆,道長,這世上最難降的妖魔是什么绳泉? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任逊抡,我火速辦了婚禮,結(jié)果婚禮上零酪,老公的妹妹穿的比我還像新娘冒嫡。我一直安慰自己,他們只是感情好四苇,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布孝凌。 她就那樣靜靜地躺著,像睡著了一般月腋。 火紅的嫁衣襯著肌膚如雪蟀架。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天罗售,我揣著相機與錄音辜窑,去河邊找鬼。 笑死寨躁,一個胖子當(dāng)著我的面吹牛穆碎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播职恳,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼所禀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了放钦?” 一聲冷哼從身側(cè)響起色徘,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎操禀,沒想到半個月后褂策,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年斤寂,在試婚紗的時候發(fā)現(xiàn)自己被綠了耿焊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遍搞,死狀恐怖罗侯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溪猿,我是刑警寧澤钩杰,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站诊县,受9級特大地震影響讲弄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翎冲,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一垂睬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抗悍,春花似錦驹饺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衔沼,卻和暖如春蝌借,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背指蚁。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工菩佑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凝化。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓稍坯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搓劫。 傳聞我的和親對象是個殘疾皇子瞧哟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法枪向,內(nèi)部類的語法勤揩,繼承相關(guān)的語法,異常的語法秘蛔,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 轉(zhuǎn)自:http://blog.csdn.net/jackfrued/article/details/4492194...
    王帥199207閱讀 8,520評論 3 93
  • “讓他去說陨亡,讓他去做傍衡,給每個孩子一顆自由的心快樂去生活”這是《自由的飛》里面的一句歌詞。 中國的教育模式就是這樣数苫,...
    Lj劉小爺閱讀 415評論 0 0
  • 此刻我躺在公司宿舍的床上虐急,忍受著重感冒帶來的鼻塞和噴嚏,一邊用昏沉的腦袋思考著我是否還要再這樣走下去滔迈,一邊期...
    63decc79a932閱讀 406評論 0 0