Daimler 旗下Smart 將進軍中國電動車市場

目前中國不少大城市出現嚴重的空氣污染情況,有人歸咎是大城市汽車很多,排出廢氣所致,若多使用電動車將有望紓緩問題,中國電動汽車市場也受到關注。Daimler 旗下的 Smart 將有望成為首間在中國發售電動汽車的品牌。

Smart 決定在中國推出 Smart Fortwo ED 電動車,Fortwo ED 在德國的銷售情況理想,佔所有電動車銷量 4 成。

Fortwo ED 為短陣版本,擁有 74 匹馬力的電動摩打,最高時速達 125 公里,單次充電後的續航距離約 145 公里。

此外,Smart 的母公司 Daimler與中國的比亞迪合營的汽車品牌 Denza,首部電動車也會在明年夏天推出。量產型號將於明年 4 月在北京車展亮相。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

東南大學研發出中國首輛無線充電電動汽車

據悉,東南大學近日研發出中國首輛無線充電電動汽車,這一技術還可以應用在家用電器、醫療設備等方面。無線電能傳輸技術即擺脫電力傳輸線路的束縛,直接通過空間磁場實現電力傳輸,為設備進行充電或供電。

電動汽車尾部安裝了一個接收端,而在地面的停車位上,裝了一個磁共振發射源,汽車通過磁共振接收能量,進而轉化為電能。東大研發的這輛3000瓦的無線充電電動汽車,慢充充滿電需要7—8小時,充滿可以跑180多公裏。

據東南大學電氣工程學院院長黃學良介紹,目前電動汽車無線充電有兩種方式,一種方式是電磁感應。只要在路面下面每隔幾英尺埋一段金屬線圈,就能利用磁場以無線方式傳輸大量電能,來驅動電動汽車。不過,這種技術對磁路設計要求苛刻,傳輸距離比較短,在大功率無線電能傳輸中有局限性。

直到另一種方式磁共振技術出現,無線電能傳輸技術才有了新的飛躍。東大研發的無線充電電動汽車用的正是磁共振技術。和電磁感應方式相比,這種方式輻射小,方向性要求不高,傳輸距離更長,傳輸效率高。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

北京上海等城市 將加大新能源車投放力度

據新華網報導,北京、上海、天津等城市,擬大量更新公交車,以減少機動車尾氣排放。中國近期霾害肆虐,正加速審核新能源政策落實。臺灣進軍中國大陸電動巴士市場的F-立凱、長園科業績將受惠此一政策。

上週北京交通部門與環保部門通過計畫,今年起5年將投資100億元(人民幣),將現有公交車大規模更新為電動車及天然氣車。今後5年,北京公交集團計畫更新13,825輛,其中新能源車(電動巴士)4,058輛。

上海則是從明年開始,將以不低於50%的比例發展新能源公交車,北汽集團、比亞迪等中國汽車業者,也都瞄準此一商機,協尋新能源電池公司。

臺灣市場也推出10年6,200輛電動巴士上路計畫,計畫明年正式啟動。 F-立凱繼今年底完成在台44台電動巴士上路後,明年也將跟進台灣、大陸兩岸政策。

長園科則著眼於大陸新能源補助金額,參與大陸中宇4.2億安時鋰電池項目開工儀式,也與大陸電芯廠潔神合作發展邯鄲市動力電池計畫,參與河北省電動巴士試點運行計畫。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

Tesla正式進軍中國 官網接受Model S/Model X預定

特斯拉(Tesla)正式進軍中國市場,Tesla中國官網12月13日已經正式上線,並開放Model S與Model X等兩種車款接受預訂,訂金均為人民幣25 萬元,實際官方售價則尚未公佈。顯示Tesla電動車已獲中國監管部門許可,即將在當地上市。

市場推測,以Model S在美國市場訂價7萬至10萬美元,加上進口車各項稅費,Model S的零售價可能在人民幣60萬至85萬元間,交貨期最早在2014年初。

早在2012年,特斯拉就計劃在北京設立展示中心,並承租約800平方公尺的店面,但目前為止尚未看到正式營運跡象。但由於Tesla在中國當地尚未取得商標使用權,目前中文官方網站是採用tuosule.cn為域名,Tesla與商標所有者的爭奪已進入法律程序。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

三星將進軍電動車市場?已申請多項相關專利

據「華爾街日報」(WSJ)報導,雖然三星集團對WSJ稱,沒有進軍電動車市場的計畫。但三星電子(Samsung Electronics)今年在美國和韓國申請的專利,涵蓋了可用在電動車的零件和技術,這些文件透露出這個財團可能在動擴大營收來源的腦筋。

根據美國專利商標局(U.S. Patent & Trademark Office)和韓國智慧財產權局訊息服務局(Korea Intellectual Property Rights Information Service)公布的專利申請文件,三星遞交的申請文件是電動車會使用的汽車零件製作新技術。三星申請的技術專利包含輪胎、引擎及分享資訊給汽車和駕駛者的車上電子產品。

電動車目前在全球市場的人氣還不高,但這為三星提供了將技術實力發揮在智慧型手機、電視和記憶體以外產品的機會,三星在競爭激烈的電視和行動裝置市場動能已經放慢。

大和證券分析指出,一旦世界進入電動車時代,車廠和電子企業的界線將日益模糊;等到電動車日益普及,三星可輕鬆加入獲利。8月公佈的專利案顯示,三星有意結合汽車和醫療科技,依照駕駛的身體情況,讓車輛接手控制。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

HEV(混合動力車輛)

混合動力車輛(Hybrid electric vehicle, HEV)),是使用兩種或以上能源的車輛,所使用的動力來源有:內燃機、電動機、電池、氫氣、燃料電池等的技術。

多數油電混合動力車使用汽油,雖然消耗汽油較少,但是加速表現卻較佳,被視為比普通由內燃引擎發動車輛較為環保的選擇。近年有的可以從輸電網絡上向內部電池充電,叫插電式混合動力汽車(Plug-in hybrid, PHEV)。

原理

絕大多數的混合動力車的推動裝置不外乎內燃機或電動機,若當中有使用電力推動電動機作為其中一種推動裝置者即可以用電池進行再生制動,把能量回收,以節省能源,現在較普遍使用的油電混合動力車就屬於這一類。油電混合動力車或柴電動力車的推動裝置可以是同時擁有電動機及內燃機引擎,也有只使用電動機的設計。

分類方式

以動力來源劃分:
1 油電混合動力 及柴電混合動力
2 燃料電池和電池混合車
3 液壓動力混合系統
4 多重燃料混合動力系統
5 人力混合動力系統

依程度分類(degree of hybridization):
1 輕度混合動力
2 中度混合動力
3 重度混合動力
4 插電式混合動力(PHEV)

依傳動配置分類(drive train structure/power train configurations):
1 並聯式油電混合系統
2 串聯混合動力系統
3 混聯式混合動力系統(動力整合/分配式混合動力系統)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

一起玩轉微服務(10)——spring boot介紹

對於Spring,相信大家都非常熟悉,從出現開始,一直是企業級開發的主流。但是隨着軟件的發展和應用開發的不斷演化,它的一些缺點也逐漸胡暴露了出來,下面,我們就一起看一下Spring的發展歷程並且認識一下Spring Boot。

由來

在Spring 1.x的時候,所有的配置都通過XML,隨着項目的擴大,需要頻繁的在java和XML之間切換。 在Spring 2.x的時候,已經開始逐步替換掉XML配置。在Spring 3.x的時候,已經開始提供java的配置方式,在4.x的時候,已經全部推薦使用java配置的方式。隨着動態語言的流行,java的開發顯得格外的繁瑣,體現在配置的複雜、開發效率低下、部署以及與第三方的集成繁雜,這個時候Spring Boot應運而生。

 

 

 Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化新 Spring 應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。簡化了基於 Spring 的應用開發,通過少量的代碼就能創建一個獨立的、產品級別的 Spring 應用。Spring Boot 為 Spring 平台及第三方庫提供開箱即用的設置,減少與第三方庫集成的複雜度。 Spring Boot 的核心思想就是約定大於配置,多數 Spring Boot 應用只需要很少的 Spring 配置。採用 Spring Boot 可以大大的簡化你的開發模式,所有你想集成的常用框架,它都有對應的組件支持。

 

特性

1.方便地創建獨立的Spring應用,為基於Spring的開發提供更快的入門體驗。2.內置嵌入tomcat,無需生成war文件。3.簡化maven配置。4.自動配置Spring,更快、更方便的與第三方應用整合,比如消息隊列、緩存等在企業級開發中常用的組件。5.提供大型項目中的非功能特性。如:指標、安全、健康檢查及外部配置。6.開箱即用,無需代碼生成,也無需XML配置,同時也能夠通過修改默認值來滿足待定的需求。

四大神器

自動配置

Spring Boot 的自動配置功能可基於類路徑檢測自動為運行中的應用配置依賴關係,不需要提供額外的XML配置。

Starters

Spring Boot 可提供一系列稱為 POM Starters 的精細依賴關係。Spring Boot 熟知如何配置這些依賴關係,同時讓組織能夠擴展 Spring Boot 來配置自定義的依賴關係。

Actuator

Actuator 可提供運行狀況檢查和指標等生產就緒型功能。這些功能通過 Spring Boot 應用內的 REST 終端提供。只需要簡單的配置就可以實現強大的監控和檢查。

開發工具

這些工具旨在縮短開發和測試周期,其中包括一個可在資源變更時觸發瀏覽器刷新的嵌入式 LiveReload 服務器。這些工具還提供了應用自動重啟功能,只要類路徑上的文件發生更改,該功能更即可啟動。重啟技術使用兩種類加載器。未更改的分類(例如來自第三方 JAR 的類)被加載到基礎類加載器,而開發中的分類則被加載到重啟類加載器。當應用重啟時,重啟類加載器會被丟棄,同時創建一個新的類加載器。這種方法意味着應用重啟的速度通常要比“冷啟動”的速度快得多,因為基礎類加載器已準備就緒且已填充完畢。從而快速實現應用的熱部署,對於簡單的修改這種場景能夠非常有效的提高效率。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

架構設計 | 高併發流量削峰,共享資源加鎖機制

本文源碼:GitHub·點這裏 || GitEE·點這裏

一、高併發簡介

在互聯網的業務架構中,高併發是最難處理的業務之一,常見的使用場景:秒殺,搶購,訂票系統;高併發的流程中需要處理的複雜問題非常多,主要涉及下面幾個方面:

  • 流量管理,逐級承接削峰;
  • 網關控制,路由請求,接口熔斷;
  • 併發控制機制,資源加鎖;
  • 分佈式架構,隔離服務和數據庫;

高併發業務核心還是流量控制,控制流量下沉速度,或者控制承接流量的容器大小,多餘的直接溢出,這是相對複雜的流程。其次就是多線程併發下訪問共享資源,該流程需要加鎖機制,避免數據寫出現錯亂情況。

二、秒殺場景

1、預搶購業務

活動未正式開始,先進行活動預約,先把一部分流量收集和控制起來,在真正秒殺的時間點,很多數據可能都已經預處理好了,可以很大程度上削減系統的壓力。有了一定預約流量還可以提前對庫存系統做好準備,一舉兩得。

場景:活動預約,定金預約,高鐵搶票預購。

2、分批搶購

分批搶購和搶購的場景實現的機制是一致的,只是在流量上緩解了很多壓力,秒殺10W件庫存和秒殺100件庫存系統的抗壓不是一個級別。如果秒殺10W件庫存,系統至少承擔多於10W幾倍的流量衝擊,秒殺100件庫存,體系可能承擔幾百或者上千的流量就結束了。下面流量削峰會詳解這裏的策略機制。

場景:分時段多場次搶購,高鐵票分批放出。

3、實時秒殺

最有難度的場景就是準點實時的秒殺活動,假如10點整準時搶1W件商品,在這個時間點前後會湧入高併發的流量,刷新頁面,或者請求搶購的接口,這樣的場景處理起來是最複雜的。

  • 首先系統要承接住流量的湧入;
  • 頁面的不斷刷新要實時加載;
  • 高併發請求的流量控制加鎖等;
  • 服務隔離和數據庫設計的系統保護;

場景:618準點搶購,雙11準點秒殺,電商促銷秒殺。

三、流量削峰

1、Nginx代理

Nginx是一個高性能的HTTP和反向代理web服務器,經常用在集群服務中做統一代理層和負載均衡策略,也可以作為一層流量控制層,提供兩種限流方式,一是控制速率,二是控制併發連接數。

基於漏桶算法,提供限制請求處理速率能力;限制IP的訪問頻率,流量突然增大時,超出的請求將被拒絕;還可以限制併發連接數。

高併發的秒殺場景下,經過Nginx層的各種限制策略,可以控制流量在一個相對穩定的狀態。

2、CDN節點

CDN靜態文件的代理節點,秒殺場景的服務有這樣一個操作特點,活動倒計時開始之前,大量的用戶會不斷的刷新頁面,這時候靜態頁面可以交給CDN層面代理,分擔數據服務接口的壓力。

CDN層面也可以做一層限流,在頁面內置一層策略,假設有10W用戶點擊搶購,可以只放行1W的流量,其他的直接提示活動結束即可,這也是常用的手段之一。

話外之意:平時參与的搶購活動,可能你的請求根本沒有到達數據接口層面,就極速響應商品已搶完,自行意會吧。

3、網關控制

網關層面處理服務接口路由,一些校驗之外,最主要的是可以集成一些策略進入網關,比如經過上述層層的流量控制之後,請求已經接近核心的數據接口,這時在網關層面內置一些策略控制:如果活動是想激活老用戶,網關層面快速判斷用戶屬性,老用戶會放行請求;如果活動的目的是拉新,則放行更多的新用戶。

經過這些層面的控制,剩下的流量已經不多了,後續才真正開始執行搶購的數據操作。

話外之意:如果有10W人參加搶購活動,真正下沉到底層的搶購流量可能就1W,甚至更少,在分散到集群服務中處理。

4、併發熔斷

在分佈式服務的接口中,還有最精細的一層控制,對於一個接口在單位之間內控制請求處理的數量,這個基於接口的響應時間綜合考慮,響應越快,單位時間內的併發量就越高,這裏邏輯不難理解。

言外之意:流量經過層層控制,數據接口層面分擔的壓力已經不大,這時候就是面對秒殺業務中的加鎖問題了。

四、分佈式加鎖

1、悲觀鎖

機制描述

所有請求的線程必須在獲取鎖之後,才能執行數據庫操作,並且基於序列化的模式,沒有獲取鎖的線程處於等待狀態,並且設定重試機制,在單位時間后再次嘗試獲取鎖,或者直接返回。

過程圖解

Redis基礎命令

SETNX:加鎖的思路是,如果key不存在,將key設置為value如果key已存在,則 SETNX 不做任何動作。並且可以給key設置過期時間,過期后其他線程可以繼續嘗試鎖獲取機制。

藉助Redis的該命令模擬鎖的獲取動作。

代碼實現

這裏基於Redis實現的鎖獲取和釋放機制。

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import javax.annotation.Resource;
@Component
public class RedisLock {

    @Resource
    private Jedis jedis ;

    /**
     * 獲取鎖
     */
    public boolean getLock (String key,String value,long expire){
        try {
            String result = jedis.set( key, value, "nx", "ex", expire);
            return result != null;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }

    /**
     * 釋放鎖
     */
    public boolean unLock (String key){
        try {
            Long result = jedis.del(key);
            return result > 0 ;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }
}

這裏基於Jedis的API實現,這裏提供一份配置文件。

@Configuration
public class RedisConfig {

    @Bean
    public JedisPoolConfig jedisPoolConfig (){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig() ;
        jedisPoolConfig.setMaxIdle(8);
        jedisPoolConfig.setMaxTotal(20);
        return jedisPoolConfig ;
    }

    @Bean
    public JedisPool jedisPool (@Autowired JedisPoolConfig jedisPoolConfig){
        return new JedisPool(jedisPoolConfig,"127.0.0.1",6379) ;
    }

    @Bean
    public Jedis jedis (@Autowired JedisPool jedisPool){
        return jedisPool.getResource() ;
    }
}

問題描述

在實際的系統運行期間可能出現如下情況:線程01獲取鎖之後,進程被掛起,後續該執行的沒有執行,鎖失效后,線程02又獲取鎖,在數據庫更新后,線程01恢復,此時在持有鎖之後的狀態,繼續執行后就會容易導致數據錯亂問題。

這時候就需要引入鎖版本概念的,假設線程01獲取鎖版本1,如果沒有執行,線程02獲取鎖版本2,執行之後,通過鎖版本的比較,線程01的鎖版本過低,數據更新就會失敗。

CREATE TABLE `dl_data_lock` (
	`id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	`inventory` INT (11) DEFAULT '0' COMMENT '庫存量',
	`lock_value` INT (11) NOT NULL DEFAULT '0' COMMENT '鎖版本',
	PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '鎖機製表';

說明:lock_value就是記錄鎖版本,作為控制數據更新的條件。

<update id="updateByLock">
    UPDATE dl_data_lock SET inventory=inventory-1,lock_value=#{lockVersion}
    WHERE id=#{id} AND lock_value &lt;#{lockVersion}
</update>

說明:這裏的更新操作,不但要求線程獲取鎖,還會判斷線程鎖的版本不能低於當前更新記錄中的最新鎖版本。

2、樂觀鎖

機制描述

樂觀鎖大多是基於數據記錄來控制,在更新數據庫的時候,基於前置的查詢條件判斷,如果查詢出來的數據沒有被修改,則更新操作成功,如果前置的查詢結果作為更新的條件不成立,則數據寫失敗。

過程圖解

代碼實現

業務流程,先查詢要更新的記錄,然後把讀取的列,作為更新條件。

@Override
public Boolean updateByInventory(Integer id) {
    DataLockEntity dataLockEntity = dataLockMapper.getById(id);
    if (dataLockEntity != null){
        return dataLockMapper.updateByInventory(id,dataLockEntity.getInventory())>0 ;
    }
    return false ;
}

例如如果要把庫存更新,就把讀取的庫存數據作為更新條件,如果讀取庫存是100,在更新的時候庫存變了,則更新條件自然不能成立。

<update id="updateByInventory">
    UPDATE dl_data_lock SET inventory=inventory-1 WHERE id=#{id} AND inventory=#{inventory}
</update>

五、分佈式服務

1、服務保護

在處理高併發的秒殺場景時,經常出現服務掛掉場景,常見某些APP的營銷頁面,出現活動火爆頁面丟失的提示情況,但是不影響整體應用的運行,這就是服務的隔離和保護機制。

基於分佈式的服務結構可以把高併發的業務服務獨立出來,不會因為秒殺服務掛掉影響整體的服務,導致服務雪崩的場景。

2、數據庫保護

數據庫保護和服務保護是相輔相成的,分佈式服務架構下,服務和數據庫是對應的,理論上秒殺服務對應的就是秒殺數據庫,不會因為秒殺庫掛掉,導致整個數據庫宕機。

六、源代碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:《架構設計系列》,蘿蔔青菜,各有所需

序號 標題
00 架構設計:單服務.集群.分佈式,基本區別和聯繫
01 架構設計:分佈式業務系統中,全局ID生成策略
02 架構設計:分佈式系統調度,Zookeeper集群化管理
03 架構設計:接口冪等性原則,防重複提交Token管理
04 架構設計:緩存管理模式,監控和內存回收策略
05 架構設計:異步處理流程,多種實現模式詳解

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

深入淺出PyTorch(算子篇)

Tensor

自從張量(Tensor)計算這個概念出現后,神經網絡的算法就可以看作是一系列的張量計算。所謂的張量,它原本是個數學概念,表示各種向量或者數值之間的關係。PyTorch的張量(torch.Tensor)表示的是N維矩陣與一維數組的關係。

torch.Tensor的使用方法和numpy很相似(https://pytorch.org/…tensor-tutorial-py),兩者唯一的區別在於torch.Tensor可以使用GPU來計算,這就比用CPU的numpy要快很多。

張量計算的種類有很多,比如加法、乘法、矩陣相乘、矩陣轉置等,這些計算被稱為算子(Operator),它們是PyTorch的核心組件。

算子的backend一般是C/C++的拓展程序,PyTorch的backend是稱為”ATen”的C/C++庫,ATen是”A Tensor”的縮寫。

Operator

PyTorch所有的Operator都定義在Declarations.cwrap和native_functions.yaml這兩個文件中,前者定義了從Torch那繼承來的legacy operator(aten/src/TH),後者定義的是native operator,是PyTorch的operator。

相比於用C++開發的native code,legacy code是在PyTorch編譯時由gen.py根據Declarations.cwrap的內容動態生成的。因此,如果你想要trace這些code,需要先編譯PyTorch。

legacy code的開發要比native code複雜得多。如果可以的話,建議你盡量避開它們。

MatMul

本文會以矩陣相乘–torch.matmul()為例來分析PyTorch算子的工作流程。

我在深入淺出全連接層(fully connected layer)中有講在GPU層面是如何進行矩陣相乘的。Nvidia、AMD等公司提供了優化好的線性代數計算庫–cuBLAS/rocBLAS/openBLAS,PyTorch只需要調用它們的API即可。

Figure 1是torch.matmul()在ATen中的function flow。可以看到,這個flow可不短,這主要是因為不同類型的tensor(2d or Nd, batched gemm or not,with or without bias,cuda or cpu)的操作也不盡相同。

at::matmul()主要負責將Tensor轉換成cuBLAS需要的格式。前面說過,Tensor可以是N維矩陣,如果tensor A是3d矩陣,tensor B是2d矩陣,就需要先將3d轉成2d;如果它們都是>=3d的矩陣,就要考慮batched matmul的情況;如果bias=True,後續就應該交給at::addmm()來處理;總之,matmul要考慮的事情比想象中要多。

除此之外,不同的dtype、device和layout需要調用不同的操作函數,這部分工作交由c10::dispatcher來完成。

Dispatcher

dispatcher主要用於動態調用dtype、device以及layout等方法函數。用過numpy的都知道,np.array()的數據類型有:float32, float16,int8,int32,…. 如果你了解C++就會知道,這類程序最適合用模板(template)來實現。

很遺憾,由於ATen有一部分operator是用C語言寫的(從Torch繼承過來),不支持模板功能,因此,就需要dispatcher這樣的動態調度器。

類似地,PyTorch的tensor不僅可以運行在GPU上,還可以跑在CPU、mkldnn和xla等設備,Figure 1中的dispatcher4就根據tensor的device調用了mm的GPU實現。

layout是指tensor中元素的排布。一般來說,矩陣的排布都是緊湊型的,也就是strided layout。而那些有着大量0的稀疏矩陣,相應地就是sparse layout。

Figure 2是strided layout的演示實例,這裏創建了一個2行2列的矩陣a,它的數據實際存放在一維數組(a.storage)里,2行2列只是這個數組的視圖。

stride充當了從數組到視圖的橋樑,比如,要打印第2行第2列的元素時,可以通過公式:\(1 * stride(0) + 1 * stride(1)\)來計算該元素在數組中的索引。

除了dtype、device、layout之外,dispatcher還可以用來調用legacy operator。比如說addmm這個operator,它的GPU實現就是通過dispatcher來跳轉到legacy::cuda::_th_addmm。

END

到此,就完成了對PyTorch算子的學習。如果你要學習其他算子,可以先從aten/src/ATen/native目錄的相關函數入手,從native_functions.yaml中找到dispatch目標函數,詳情可以參考Figure 1。

更多精彩文章,歡迎掃碼關注下方的公眾號, 並訪問我的簡書博客:https://www.jianshu.com/u/c0fe8671254e

歡迎轉發至朋友圈,工作號轉載請後台留言申請授權~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

MyBatis入門學習-連接oracle實現CURD基本操作

目錄

  • 前言
  • 導入oracle庫
  • 配置
    • 環境配置
    • 配置引用
    • 配置映射
  • 查詢
    • 單條件查詢
    • 多條件查詢
      • 通過類字段傳遞參數
      • 通過Map接口傳參
      • Param註解
  • 插入
  • 更新
  • 刪除
  • 字段映射
  • 參考文獻

前言

本篇記錄使用mybatis連接oracle數據庫實現基本的CURD操作。

導入oracle庫

由於oracle收費, 因此maven沒有oracle庫包,需要我們自己導入,可以手工導入外部包,也可以將oracle的jar導入到maven庫種。具體導入步驟可以查看Maven添加Oracle的依賴及驅動

導入mybatis庫包,我本地使用的是3.5.5版本。最後的配置如下所示


<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.5</version>
</dependency>

<dependency>
  <groupId>com.oracle.jdbc</groupId>
  <artifactId>ojdbc6</artifactId>
  <version>11.2.0.1.0</version>
</dependency>

配置

準備mybatis的配置,在resources目錄下新建一個mybatis-config.xml文件,配置如下

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根標籤 -->
<configuration>
    <properties>
        <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@10.60.45.239:1521:devdb" />
        <property name="username" value="fgmain10001" />
        <property name="password" value="test1" />
    </properties>

    <!-- 環境,可以配置多個,default:指定採用哪個環境 -->
    <environments default="test">
        <!-- id:唯一標識 -->
        <environment id="test">
            <!-- 事務管理器,JDBC類型的事務管理器 -->
            <transactionManager type="JDBC" />
            <!-- 數據源,池類型的數據源 -->
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                <property name="url" value="jdbc:oracle:thin:@10.60.45.239:1521:devdb" />
                <property name="username" value="fgmain10001" />
                <property name="password" value="test1" />
            </dataSource>
        </environment>
        <environment id="development">
            <!-- 事務管理器,JDBC類型的事務管理器 -->
            <transactionManager type="JDBC" />
            <!-- 數據源,池類型的數據源 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 -->
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="singleTransMapper.xml" />
    </mappers>
</configuration>

環境配置

 <environment id="test">
      <!-- 事務管理器,JDBC類型的事務管理器 -->
      <transactionManager type="JDBC" />
      <!-- 數據源,池類型的數據源 -->
      <dataSource type="POOLED">
          <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
          <property name="url" value="jdbc:oracle:thin:@10.60.45.239:1521:devdb" />
          <property name="username" value="fgmain10001" />
          <property name="password" value="test1" />
      </dataSource>
  </environment>

其中environments可以配置多個環境的oracle數據源。

id是環境變量的編號,在<environments>default中可以設置當前的環境值。
dataSource中設置數據源。類型有3種。包括:POOLED池化,UNPOOLED非池化和JNDI從其他配置元加載。
driver配置的類名,oracle填寫oracle.jdbc.driver.OracleDriver
url為配置的數據源,使用239測試庫jdbc:oracle:thin:@10.60.45.239:1521:devdb
username是用戶名。
password是密碼。

配置引用

在value中可以填寫如${變量名}的配置引用,通過在properties/propertie添加對應的實際的配置值。

<configuration>
    <properties>
        <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
    </properties>
    
    <environments default="test">
        ...
        <environment id="test">
            ...
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 -->
                ...
            </dataSource>
        </environment>
    </environments>
</configuration>

配置映射

配置好數據源后,需要添加對應的表映射,映射包括CRUD對應的SQL語句以及與類之間的映射關係。


<configuration>
  ...
    <mappers>
        <mapper resource="singleTransMapper.xml" />
    </mappers>
</configuration>

在resources目錄下新建一個singleTransMapper.xml文件,MyBatis會將singleTransMapper.xml映射到對應的類

除了resources以外MyBatis還支持classurlpackage共四種配置

class可以配置具體類名,如com.mybatistest.DAO.SingleTransMapper
url可以配置完整的文件路徑,如file:///var/mappers/PostMapper.xml
package可以配置package名稱,註冊所有接口。

查詢


public class SingletransDTO {

    public String EnterpriseNum;

    public String TransNo;

    public String CommandCode;

    public int State;
}

單條件查詢

增加一個查詢單筆的語句,通過輸入流水號,返回查詢到的單筆信息。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
    <select id="selectSingle" parameterType="String" resultType="DTO.SingletransDTO">
    select * from se_singletrans where transno = #{transno}
  </select>
</mapper>

namespace需要對應到java中的類,參數和返回類型也需要一致。

在mapper節點下添加select表示select語句
parameterType為輸入的參數
resultType為返回的類型,返回類型需要對應java中的類


public interface SingleTransMapper {
    SingletransDTO selectSingle(String transNo);
}


String resource = "mybatis-config.xml";
//加載資源
InputStream inputStream = Resources.getResourceAsStream(resource);
//創建session
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
  //獲取單筆映射對象
    SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
    //根據流水號查詢
    SingletransDTO blog = mapper.selectSingle("642EHDCS899XKF8P");

    if(blog != null) {
        System.out.println(blog.ENTERPRISENUM);
        System.out.println(blog.TRANSNO);
        System.out.println(blog.COMMANDCODE);
    }else{
        System.out.println("not found");
    }

}catch (Exception exception)
{
    System.out.println(exception.getMessage());
}

多條件查詢

通過類字段傳遞參數

添加一個查詢配置selectSingleByParam

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
   
   ...
    <select id="selectSingleByClass" resultType="DTO.SingletransDTO">
    select * from se_singletrans where transno = #{TransNo} and commandCode= #{CommandCode}
  </select>
</mapper>

對應的映射類添加方法對應的方法,MyBatis可以通過反射將類的字段映射到SQL的參數,需要注意的是類的字段名和sql中配置的大小寫需要一致。


public interface SingleTransMapper {
  ...
  SingletransDTO selectSingleByClass(SingleCondition singleCondition);
}
public class SingleCondition {
    /**
     * 流水號
     */
    public String TransNo;

    /**
     * 指令類型
     */
    public String CommandCode;

    public SingleCondition(String transNo, String commandCode)
    {
        TransNo = transNo;
        CommandCode = commandCode;
    }
}

調用構造函數類的多條件查詢方案

...
SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
SingletransDTO blog = mapper.selectSingleByClass(new SingleCondition( "642EHDCS899XKF8P","10009"));

通過Map接口傳參

另一種方案可以通過傳入HashMap,MayBatis會根據key自動映射到對應的參數。
下面實現通過流水號和指令類型查詢。
添加一個查詢配置selectSingleByMultCondition

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
    ...
    <select id="selectSingleByMultCondition" resultType="DTO.SingletransDTO">
    select * from se_singletrans where transno = #{transNo} and commandCode= #{commandCode}
  </select>
</mapper>

添加對應的方法,傳入參數為HashMap<String,Object> param

public interface SingleTransMapper {
  ...
    SingletransDTO selectSingleByMultCondition(HashMap<String,Object> param);
}

修改調用新的多條件查詢方法

...
//獲取單筆映射對象
SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
//根據流水號查詢
HashMap<String,Object> param = new HashMap<String,Object>();
param.put("transNo","642EHDCS899XKF8P");
param.put("commandCode","10009");
SingletransDTO blog = mapper.selectSingle2(param);
...

需要注意的是,由於HashMap的key是不區分大小寫的,因此需要和配置文件sql的參數大小寫一致。

Param註解

通過類參數和Map進行多條件查詢都需要創建額外的對象,另一種比較好的方式可以通過在方法參數上添加Param註解的方式配置方法參數和SQL參數的映射關係。

添加一個查詢配置selectSingleByParam

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
   
   ...
    <select id="selectSingleByParam" resultType="DTO.SingletransDTO">
    select * from se_singletrans where transno = #{param1} and commandCode= #{param2}
  </select>
</mapper>

對應的映射類添加方法對應的方法,這樣MyBatis就知道參數映射規則,就會自動映射,需要注意的數參數和sql中配置的大小寫也需要一致。


public interface SingleTransMapper {
    SingletransDTO selectSingle(String transNo);
    SingletransDTO selectSingleByMultCondition(HashMap<String,Object> param);
    SingletransDTO selectSingleByParam(@Param("param1")String transNo, @Param("param2") String commandCode);
}

調用註解傳參方法

...
//獲取單筆映射對象
SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
SingletransDTO blog = mapper.selectSingleByParam("642EHDCS899XKF8P","10009");
...

插入

在mapper下添加insert表示插入的sql映射。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
  
  ...
  <insert id="insert" parameterType="DTO.SingletransDTO">
    insert into se_singletrans(ENTERPRISENUM,TRANSNO,COMMANDCODE,STATE) values(#{EnterpriseNum},#{TransNo},#{CommandCode},#{State})
  </insert>
</mapper>

添加類對應的insert方法


public interface SingleTransMapper {

    ...
    int insert(SingletransDTO singletransDTO);
}

SqlSession默認會開啟事務,在insert完成后需要調用SqlSessioncommit()方法提交事務。


try (SqlSession session = sqlSessionFactory.openSession()) {
    SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
    SingletransDTO singletransDTO = new     SingletransDTO();
    singletransDTO.EnterpriseNum  = "QT330001";
    singletransDTO.TransNo = "MYBATIS.INSERT";
    singletransDTO.CommandCode = "10009";
    int count = mapper.insert(singletransDTO);
    session.commit();
    System.out.println("insert result:" +count);
}catch (Exception exception)
{
    System.out.println(exception.getMessage());
}

我們也可以調用SqlSession openSession(boolean autoCommit)傳入參數,自動提交。

更新

在mapper下添加update節點表示插入,插入時可以對插入的字段設置條件,達成某條件是該字段才需要更新。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
  
  ...
   <update id="update" parameterType="DTO.SingletransDTO">
    update se_singletrans
    <set>
        <if test="State != null and State!=''"></if>
        STATE=#{State}
    </set>
    where transno = #{TransNo} and commandCode= #{CommandCode}
  </update>
</mapper>

添加類對應的update方法


public interface SingleTransMapper {

    ...
    int update(SingletransDTO singletransDTO);
}

SqlSession默認會開啟事務,和insert一樣,在update完成后需要調用SqlSessioncommit()方法提交事務。


try (SqlSession session = sqlSessionFactory.openSession()) {
    SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
    SingletransDTO singletransDTO = new SingletransDTO();
    singletransDTO.EnterpriseNum = "QT330001";
    singletransDTO.TransNo = "MYBATIS.INSERT";
    singletransDTO.CommandCode = "10009";
    singletransDTO.State = 2;
    int count = mapper.update(singletransDTO);
    session.commit();
    System.out.println("update result:" +count);
}catch (Exception exception)
{
    System.out.println(exception.getMessage());
}

刪除

在mapper下添加delete節點表示刪除。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">
  
  ...
   
  <delete id="delete">
    delete from se_singletrans where transno = #{TransNo} and commandCode= #{CommandCode}
  </delete>
</mapper>

添加類對應的delete方法,可以通過參數註解的方式指定參數。


public interface SingleTransMapper {

    ...
    int delete(@Param("TransNo")String transNo, @Param("CommandCode") String commandCode);
}

SqlSession默認會開啟事務,在delete完成后需要調用SqlSessioncommit()方法提交事務。


try (SqlSession session = sqlSessionFactory.openSession()) {
    SingleTransMapper mapper = session.getMapper(SingleTransMapper.class);
    int count = mapper.delete("MYBATIS.INSERT","10009");
    session.commit();
    System.out.println("delete result:" +count);
}catch (Exception exception)
{
    System.out.println(exception.getMessage());
}

字段映射

若字段名和數據庫的字段名不一致,可以通過配置進行映射。添加resultMap節點,配置類字段和數據庫字段的映射關係,若沒有配置的字段,則根據默認MyBatis的映射關係處理,即字段名一樣的自動映射,MyBatis會嘗試進行類型轉換,若轉換異常,則可能拋錯。我們也可以通過typeHandler自定義自己的類型處理器。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DAO.SingleTransMapper">

  <resultMap id="singleResultMap" type="DTO.SingletransDTO">
    <result property="TransNo"  column="transNo" />
    <result property="CommandCode" column="commandCode"/>
    <result property="SpecialProperty" typeHandler="CustomTypeHandle" column="SpecialColumn"/>
  </resultMap>
  <select id="selectSingleToReusltMap" resultMap="singleResultMap">
    select * from se_singletrans where transno = #{param1} and commandCode= #{param2}
  </select>
</mapper>

關於TypeHandle這裏不做具體闡述,有興趣的可以看下MyBatis自定義類型處理器 TypeHandler

參考文獻

  1. Maven添加Oracle的依賴及驅動
  2. MyBatis自定義類型處理器 TypeHandler

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?