日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

本文介紹了MyBatis支持多個(gè)數(shù)據(jù)庫(kù)的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!

問題描述

我有不同的客戶使用不同的數(shù)據(jù)庫(kù)供應(yīng)商(Postgres、Oracle、MySQL等)

我希望只編寫一次代碼,并且能夠在不同的數(shù)據(jù)庫(kù)上運(yùn)行。

實(shí)現(xiàn)這一目標(biāo)的”mybatis”方法是什么?

我到目前為止發(fā)現(xiàn)的問題,例如:

Postgres在CREATE SQL語(yǔ)句中有一個(gè)”如果不存在”的概念。Oracle不支持此功能。
Oracle在SQL語(yǔ)法中不支持”Limit”和”Offset”,而其他數(shù)據(jù)庫(kù)則支持。
DDL語(yǔ)句中的文本(Postgres)與lob(Oracle和其他)JDBC類型。

我不想重復(fù)我的查詢(這就是我到目前為止所做的)。也許有一種更優(yōu)雅的方式可以做到這一點(diǎn)。

我正在使用mybatis Java批注。

推薦答案

您說(shuō)您使用的是批注,但我建議您使用XML語(yǔ)言。我通常覺得它更清楚,特別是因?yàn)椴樵冎械哪承┎糠譄o(wú)論如何都需要完全更改。

下面是一個(gè)DDL示例,其中為相同的方法獲取了兩個(gè)不同的XML元素,但數(shù)據(jù)庫(kù)ID不同。這些表非常相似,但由于您檢查表是否已經(jīng)存在以及類型是否完全不同的方式,您無(wú)法真正避免為此使用不同的SQL代碼:

<update id="createTables" databaseId="postgresql">
    DO $$
    BEGIN
        CREATE TABLE IF NOT EXISTS item (
            id SERIAL PRIMARY KEY,
            content TEXT,
            creation_datetime TIMESTAMPTZ DEFAULT NOW(),
            modification_datetime TIMESTAMPTZ
        );
    END$$
</update>
<update id="createTables" databaseId="sqlserver">
    IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'item')
    BEGIN
        CREATE TABLE item (
            id INT IDENTITY PRIMARY KEY,
            content NVARCHAR(MAX),
            creation_datetime DATETIMEOFFSET DEFAULT SYSDATETIMEOFFSET(),
            modification_datetime DATETIMEOFFSET
        );
    END
</update>

您也可以將查詢放在一個(gè)SQL元素中,但根據(jù)數(shù)據(jù)庫(kù)ID使用<if>(或<choose>)更改不同的節(jié)。如果更改很小,則效果很好:

<delete id="deleteItem">
    DELETE FROM my_item
    WHERE gid=CAST(#{gid} AS <if test="_databaseId == 'postgresql'">UUID</if><if test="_databaseId == 'sqlserver'">UNIQUEIDENTIFIER</if>)
</delete>

<select id="getLatestSomething" resultType="test.Something">
    SELECT <if test="_databaseId == 'sqlserver'">TOP 1</if> *
    FROM something
    ORDER BY creation_datetime DESC
    <if test="_databaseId == 'postgresql'">
    LIMIT 1
    </if>
</select>

對(duì)于不同的數(shù)據(jù)庫(kù)ID使用不同的查詢?cè)兀€是在相同的查詢?cè)刂兄皇褂脳l件片段,這是一個(gè)可讀性問題。它可能非常主觀,具體取決于查詢的復(fù)雜程度。

例如,我發(fā)現(xiàn)下面使用PostgreSQL和SQL Server的”upsert”很難讀懂。最好放在單獨(dú)的元素中:

<insert id="insertStuff" parameterType="somestuff.Stuff">
    <if test="_databaseId == 'postgresql'">
        INSERT INTO my_stuff (...)
    </if>
    <if test="_databaseId == 'sqlserver'">
        MERGE INTO my_stuff WITH (HOLDLOCK) AS t USING (
    </if>
            VALUES (#{...},
                    <if test="_databaseId == 'postgresql'">
                        CAST(#{jsonData} AS JSONB)
                    </if>
                    <if test="_databaseId == 'sqlserver'">
                        #{jsonData}
                    </if>
            )
    <if test="_databaseId == 'postgresql'">
            ON CONFLICT DO NOTHING
    </if>
    <if test="_databaseId == 'sqlserver'">
        )
              AS s (...)
              ON t....=s....
                 AND t....=s....
        WHEN NOT MATCHED BY TARGET THEN
            INSERT (...)
            VALUES (s...., s....);
    </if>
</insert>

MyBatis Dynamic SQL documentation中有關(guān)于所有這些的更多信息。


假設(shè)您的XML映射器文件位于mypackage/MyMapper.xml中,則可以在與該目錄匹配的包中使用MyMapperJava接口。沒有特定于該數(shù)據(jù)庫(kù)ID的內(nèi)容。

package mypackage;

public interface MyMapper {
    void createTables();
    void deleteItem(@Param("gid") UUID gid);
    Something getLatestSomething();
}

將MyBatis與Spring配合使用時(shí),可以這樣設(shè)置供應(yīng)商配置:

@Bean
public VendorDatabaseIdProvider vendorDatabaseIdProvider() {
    Properties vendorProperties = new Properties();
    vendorProperties.setProperty("PostgreSQL", "postgresql");
    vendorProperties.setProperty("SQL Server", "sqlserver");
    // Add others as required, this will look for the substring in the product name coming
    // from the database metadata.

    // ...
    VendorDatabaseIdProvider dbIdProvider = new VendorDatabaseIdProvider();
    dbIdProvider.setProperties(vendorProperties);
    return dbIdProvider;
}

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ApplicationContext appContext,
        VendorDatabaseIdProvider vendorDatabaseIdProvider) throws Exception {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setDatabaseIdProvider(vendorDatabaseIdProvider);

    SqlSessionFactory factory = bean.getObject();
    return factory;
}

如果您沒有使用Spring,您應(yīng)該能夠使用XML configuration配置DatabaseIdProvider

您并不嚴(yán)格需要數(shù)據(jù)庫(kù)ID提供程序。它所做的就是根據(jù)從DataSource獲得的產(chǎn)品名稱在配置中設(shè)置數(shù)據(jù)庫(kù)ID。大致是這樣的:

String databaseId = databaseIdProvider.getDatabaseId(dataSource);
configuration.setDatabaseId(databaseId);

(如果查看org.apache.ibatis.mapping.VendorDatabaseIdProvider的代碼,您會(huì)發(fā)現(xiàn)databaseIdProvider.getDatabaseId(...)只是在DatabaseMetaData.getDatabaseProductName()返回的內(nèi)容中查找匹配子字符串。如果需要,您也可以通過其他設(shè)置手動(dòng)完成此操作。)

請(qǐng)注意,當(dāng)databaseId=""直接用作XML元素的屬性時(shí),沒有下劃線,但當(dāng)用作測(cè)試條件時(shí),稱為_databaseId

這篇關(guān)于MyBatis支持多個(gè)數(shù)據(jù)庫(kù)的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,

分享到:
標(biāo)簽:errorMyBatissupportformultipledatabases exception Ibatis IT資訊 mybatis Oracl
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定