MyBatis-16MyBatis动态SQL之【支持多种数据库】

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介: MyBatis-16MyBatis动态SQL之【支持多种数据库】

概述


MyBatis-15MyBatis动态SQL之【bind】 bind标签并不能解决更换数据库带来的所有问题。 那么还有没其他的方式来支持不同的数据库呢 ?


答案是 使用if标签以及由MyBatis提供的databaseIdProvider数据库厂商标识配置


MyBatis可以根据不同的数据库厂商执行不同的SQL,这种多厂商的支持是基于映射语句中的databaseId属性。 MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。 如果同时找到了带有databaseId和不带databaseId的相同语句,则不带databaseId的将被舍弃。


配置


1.MyBatis全局配置文件增加


为了支持多厂商数据库,需要在MyBatis全局配置文件中加入databaseIdProvider配置 <databaseIdProvider type="DB_VENDOR"/>


也可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider 并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider


DB_VENDOR会通过DatabaseMetaData#getDatabaseProductName()返回的字符串进行设置, 通常情况下这个字符串比较长而且相同产品的不同版本会返回不同的值,通常会设置属性别名使其变短。

    <!-- 多数据库支持 -->
    <databaseIdProvider type="DB_VENDOR">
        <property  name ="SQL  Server" value="sqlserver"/>
        <property  name ="DB2" value ="db2"/>
        <property  name ="Oracle" value ="oracle"/>
        <property  name ="MySQL" value ="mysql"/>
        <property  name ="PostgreSQL" value ="postgresql"/>
        <property  name ="Derby" value ="derby"/>
        <property  name ="HSQL" value ="hsqldb"/>
        <property  name ="H2" value ="h2"/>
    </databaseIdProvider>


上述列举了常见的数据库产品名称,在有property配置时,databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值,如果没有匹配则置为null .


DB_VENDOR的匹配策略为DatabaseMetaData#getDatabaseProductName()返回的字符串包含property中name部分的值即可匹配。


数据库产品名一般由选择的当前数据库的JDBC驱动所决定,只要找到对应数据库DatabaseMetaData的实现类,一般在getDatabaseProductName()方法中就可以直接找到该值。

任何情况下都可以通过调用DatabaseMetaData#getDatabaseProductName()来获取具体的值


完整的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 resource="db.properties"/>
    <settings>
        <!-- 通过logImpl属性指定使用LOG4J输出日志,mybatis默认使用log4j作为输出日志信息。 -->
        <setting name="logImpl" value="LOG4J" />
        <!-- 通过配置这个属性为true可以自动将下画线方式命名的数据库列映射到java对象驼峰式命名属性中
        <setting name="mapUnderscoreToCamelCase" value="true"/>
         -->
    </settings>
    <!-- typeAliases元素下配置了一个包的别名,通常确定一个类的时候需要使用全限定名,
        比如 com.artisan.mybatis.simple.mapper.model.Country
    -->
    <typeAliases>
        <package name="com.artisan.mybatis.simple.model" />
    </typeAliases>
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池-->
            <dataSource type="UNPOOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    <!-- 多数据库支持 -->
    <databaseIdProvider  type="DB_VENDOR" >
        <property  name ="SQL  Server" value="sqlserver"/>
        <property  name ="DB2" value ="db2"/>
        <property  name ="Oracle" value ="oracle"/>
        <property  name ="MySQL" value ="mysql"/>
        <property  name ="PostgreSQL" value ="postgresql"/>
        <property  name ="Derby" value ="derby"/>
        <property  name ="HSQL" value ="hsqldb"/>
        <property  name ="H2" value ="h2"/>
    </databaseIdProvider>
    <mappers>
        <!-- 配置具体的mapper -->
        <mapper resource="com/artisan/mybatis/simple/mapper/CountryMapper.xml" />
        <!-- 逐一配置,比较繁琐,容易遗漏,接口方式不推荐
        <mapper resource="com/artisan/mybatis/xml/mapper/UserMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/UserRoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/PrivilegeMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RolePrivilegeMapper.xml"/>
         -->
        <!-- 推荐:通过包的方式配置,mybatis会先查找对应包下的所有的接口 -->
        <package name="com.artisan.mybatis.xml.mapper"/>
    </mappers>
</configuration>


注意databaseIdProvider节点的位置。


2.映射文件中的标签调整包含databaseId属性

除了增加上述配置之外,映射文件也需要调整,关键在于下面几个映射文件的标签中含有的databaseId属性


  • select
  • insert
  • update
  • delete
  • selectKey
  • sql

示例


20180428040311282.png


举个简单的例子,查询当前时间

我们知道 mysql中的语句为

select now() from dual


oracle中为

select sysdate from dual


增加个查询当前时间的接口


结合mybatis全局配置文件中的 mappers-package节点,在com.artisan.mybatis.xml.mapper包中增加接口

MultiDBMapper.java

package com.artisan.mybatis.xml.mapper;
public interface MultiDBMapper {
    String getSysTime();
}

编写映射文件


MultiDBMapper.xml


<?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接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->                    
<mapper namespace="com.artisan.mybatis.xml.mapper.MultiDBMapper">
    <select id="getSysTime"  resultType="String" databaseId="mysql">
        select now() from dual
    </select>
     <select id="getSysTime"   resultType="String" databaseId="oracle">
         select  'oralce-'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss')  from dual 
     </select>
</mapper>   


单元测试

package com.artisan.mybatis.xml.mapper;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.util.Properties;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class MultiDBMapperTest extends BaseMapperTest {
    public String getDatabaseProductName() {
        String productName = null;
        try {
            String dbfile = "db.properties";
            InputStream in = ClassLoader.getSystemResourceAsStream(dbfile);
            Properties p = new Properties();
            p.load(in);
            Class.forName(p.getProperty("jdbc.driver"));
            String url = p.getProperty("jdbc.url");
            String user = p.getProperty("jdbc.username");
            String pass = p.getProperty("jdbc.password");
            Connection con = DriverManager.getConnection(url, user, pass);
            DatabaseMetaData dbmd = con.getMetaData();
            productName = dbmd.getDatabaseProductName();
            System.out.println("数据库名称是:" + productName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return productName;
    }
    @Test
    public void getSysTimeTest() {
        // 获取数据库名称
        getDatabaseProductName();
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        // 获取MultiDBMapper
        MultiDBMapper multiDBMapper = sqlSession.getMapper(MultiDBMapper.class);
        // 调用接口方法
        String sysTime = multiDBMapper.getSysTime();
        System.out.println("当前时间:" + sysTime);
        sqlSession.close();
    }
}


日志

2018-04-27 16:05:57,730  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-27 16:05:57,730  INFO [main] (BaseMapperTest.java:29) - reader close successfully
数据库名称是:MySQL
2018-04-27 16:05:57,819 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: select now() from dual 
2018-04-27 16:05:57,929 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 
2018-04-27 16:05:57,959 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: now()
2018-04-27 16:05:57,959 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 2018-04-27 16:05:57.0
2018-04-27 16:05:57,969 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
当前时间:2018-04-27 16:05:57.0


当基于不同的数据库运行时,MyBatis会根据配置找到合适的SQL去执行。


注意事项

我们在上面演示了基于databaseId的基本用法,实际在工作中,大部分的SQL还是相同的,没有必要写成2个。这样会导致大量重复的SQL。


数据库的更换可能只会引起某个SQL语句的部分不同, 可以使用if标签配合默认的上下文中的_databaseId参数去实现。

我们用前几篇博文的例子来演示下

改造前

<select id="selectSysUsersAdvancedWithWhere" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                and user_name like concat('%',#{userName},'%')
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>


改造后

<!-- 多数据库的支持 BEGIN -->
    <select id="selectSysUsersAdvancedMulitDB" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                <if test="_databaseId == 'mysql' ">
                    and user_name like concat('%',#{userName},'%')
                </if>
                <if test="_databaseId == 'oracle' ">
                    and user_name like '%'||#{username}||'%'
                </if>
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>
    <!-- 多数据库的支持 END -->


增加个接口方法,方便区分测试

/**
     * 
     * 
     * @Title: selectSysUsersAdvancedMulitDB
     * 
     * @Description: selectSysUsersAdvancedMulitDB
     * 
     * @param sysUser
     * @return
     * 
     * @return: List<SysUser>
     */
    List<SysUser> selectSysUsersAdvancedMulitDB(SysUser sysUser);


单元测试

@Test
    public void selectSysUsersAdvancedMulitDBTest() {
        logger.info("selectSysUsersAdvancedMulitDBTest");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        List<SysUser> userList = null;
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            logger.info("===========1.当用户只输入用户名时,需要根据用户名模糊查询===========");
            // 模拟前台传参 1.当用户只输入用户名时,需要根据用户名模糊查询
            SysUser sysUser = new SysUser();
            sysUser.setUserName("ad");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有1条数据
            Assert.assertTrue(userList.size() == 1);
            logger.info("userList:" + userList);
            // 为了测试 匹配多条记录的情况,我们将id=1001这条数据的userName 由test 改为artisan
            sysUser.setUserName("i");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin和artisan, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有2条数据
            Assert.assertTrue(userList.size() == 2);
            logger.info("userList:" + userList);
            logger.info("===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========");
            // 模拟前台传参 2.当用户只输入邮箱使,根据邮箱进行完全匹配
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvanced(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            sysUser.setUserEmail("1admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info("===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========");
            // 模拟组合查询条件,存在记录的情况
            sysUser.setUserName("i");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertEquals("admin@artisan.com", sysUser.getUserEmail());
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            logger.info("===========4.当用户同时输入无法匹配的用户名和密码===========");
            // 模拟组合查询条件,不存在记录的情况
            sysUser.setUserName("x");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info(userList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-27 16:22:51,822  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-27 16:22:51,826  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-27 16:22:51,827  INFO [main] (UserMapperTest.java:934) - selectSysUsersAdvancedMulitDBTest
2018-04-27 16:22:51,857  INFO [main] (UserMapperTest.java:943) - ===========1.当用户只输入用户名时,需要根据用户名模糊查询===========
2018-04-27 16:22:51,987 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') 
2018-04-27 16:22:52,086 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: ad(String)
2018-04-27 16:22:52,157 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,157 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,167 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,167  INFO [main] (UserMapperTest.java:953) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') 
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String)
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 2
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:964) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018], SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:966) - ===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE 1=1 and user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), admin@artisan.com(String)
2018-04-27 16:22:52,187 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,187 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:972) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), 1admin@artisan.com(String)
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-27 16:22:52,197  INFO [main] (UserMapperTest.java:978) - ===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), admin@artisan.com(String)
2018-04-27 16:22:52,197 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,207 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:987) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:989) - ===========4.当用户同时输入无法匹配的用户名和密码===========
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: x(String), admin@artisan.com(String)
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:995) - []
2018-04-27 16:22:52,217  INFO [main] (UserMapperTest.java:1001) - sqlSession close successfully 


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
21天前
|
SQL 机器学习/深度学习 人工智能
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
本文系统性地阐述了自然语言转SQL(NL2SQL) 技术如何让非技术背景的业务分析师实现数据自助查询,从而提升数据驱动决策的效率与准确性。
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
|
4月前
|
SQL 存储 关系型数据库
第二篇:关系型数据库的核心概念与 SQL 基础
本篇内容深入浅出地讲解了关系型数据库的核心概念与SQL基础,适合有一定计算机基础的学习者。文章涵盖数据库的基本操作(CRUD)、数据类型、表的创建与管理等内容,并通过实例解析SELECT、INSERT、UPDATE、DELETE等语句的用法。此外,还推荐了多种学习资源与实践建议,帮助读者巩固知识。学完后,你将掌握基础数据库操作,为后续高级学习铺平道路。
210 1
|
3月前
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
241 62
|
2月前
|
SQL 缓存 监控
SqlRest让SQL秒变Http API,还支持20+数据库(含国产数据库)
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
2月前
|
SQL 存储 数据库
SQL Server Management Studio (SSMS) 21 - 微软数据库管理工具
SQL Server Management Studio (SSMS) 21 - 微软数据库管理工具
425 0
|
2月前
|
SQL XML Java
配置Spring框架以连接SQL Server数据库
最后,需要集成Spring配置到应用中,这通常在 `main`方法或者Spring Boot的应用配置类中通过加载XML配置或使用注解来实现。
218 0
|
4月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
289 5
|
3月前
|
SQL 人工智能 关系型数据库
GitHub 热门!MindsDB 破解 AI + 数据库瓶颈,究竟有什么惊艳亮点?只需 SQL 即可实现智能预测
MindsDB 是一款将 AI 能力直接注入数据库的开源工具,支持 MySQL、PostgreSQL 等多种数据库连接,通过 SQL 即可完成模型训练与预测。它提供 AutoML 引擎、LLM 集成、联邦查询等功能,简化 MLOps 流程,实现数据到智能的无缝衔接。项目在 GitHub 上已获 32.4k 星,社区活跃,适用于客户流失预警、推荐系统、情感分析等场景。开发者无需深入模型细节,即可快速构建智能解决方案。项目地址:https://github.com/mindsdb/mindsdb。
689 0
|
5月前
|
SQL 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
|
5月前
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。