Mybatis 配置多个数据源的方式

MyBatis 多数据源支持 MyBatis 支持多数据源配置并与 Spring 框架无缝集成。通过为每个数据源配置单独的DataSource,可以轻松实现对多个数据库的访问。在复杂的场景下,还可以使用实现动态数据源切换。通过合理使用多数据源配置,能够实现读写分离、模块分离和跨系统集成,从而提升系统的性能和灵活性。在开发过程中,确保每个数据源的配置正确,事务管理器和数据源的绑定清晰,是确保多数据源功能正常工作的关键。 阅读详情

properties 属性文件的实现方式

数据库连接的 properties 配置文件,配置两个数据源信息:

spring.jdbc.driver=com.mysql.cj.jdbc.Driver
spring.jdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.jdbc.username=root
spring.jdbc.password=123456

mybatis.jdbc.driver=com.mysql.cj.jdbc.Driver
mybatis.jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
mybatis.jdbc.username=root
mybatis.jdbc.password=123456

Mybatis 配置文件,配置两个 environment:

<!-- 引入数据库配置文件 -->
<properties resource="database.properties"/>

<environments default="Spring">
    <environment id="Spring">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${spring.jdbc.driver}"/>
            <property name="url" value="${spring.jdbc.url}"/>
            <property name="username" value="${spring.jdbc.username}"/>
            <property name="password" value="${spring.jdbc.password}"/>
        </dataSource>
    </environment>

    <environment id="Mybatis">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${mybatis.jdbc.driver}"/>
            <property name="url" value="${mybatis.jdbc.url}"/>
            <property name="username" value="${mybatis.jdbc.username}"/>
            <property name="password" value="${mybatis.jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

通过 DataSourceSessionFactory 工具类,获取 SqlSessionFactory:

package cn.worstone.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Optional;

public final class DataSourceSessionFactory {

    private static String MybatisConfigPath = "mybatis.xml";
    private static Map<DataSourceEnvironment, SqlSessionFactory> sessionFactoryMap = new HashMap<>();

    /**
     * Mybatis 配置的 Environment 中的数据源的枚举类型(即 Environment 的 id 属性值)
     */
    public static enum DataSourceEnvironment {
        Spring,
        Mybatis;
    }

    public static SqlSessionFactory getSessionFactory(DataSourceEnvironment dataSourceEnvironment) {
        SqlSessionFactory sqlSessionFactory = DataSourceSessionFactory.sessionFactoryMap.get(dataSourceEnvironment);
        sqlSessionFactory = Optional.ofNullable(sqlSessionFactory).orElseGet(()->{
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream(DataSourceSessionFactory.MybatisConfigPath);
            } catch (IOException e) {
                e.printStackTrace();
            } 
            SqlSessionFactory temp = new SqlSessionFactoryBuilder().build(inputStream, dataSourceProperties);
            sessionFactoryMap.put(dataSourceProperties, temp);
            return temp;
        });

        return sqlSessionFactory;
    }
}

扩展

定义一个统一的 Mapper 标识接口,每一个具体的 Mapper 接口继承该接口:

package cn.worstone.mapper;

/**
 * 通用的 Mapper 接口, 可以定制所有的通用方法, 设置参数类型为 Map<String, Object>
 */
public interface Mapper {
}

定义一个 Mapper 代理工厂,并获取 Mapper 代理,便于在执行完 Mapper 中的方法后关闭 SqlSession:

package cn.worstone.utils;

import cn.worstone.mapper.Mapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public final class MapperFactory {

    public static <T> T createMapper(Class<? extends Mapper> clazz, DataSourceSessionFactory.DataSourceEnvironment dataSourceEnvironment, boolean isCommit) {
        SqlSessionFactory sqlSessionFactory = MapperFactory.getSqlSessionFactory(dataSourceEnvironment);
        SqlSession sqlSession = sqlSessionFactory.openSession(isCommit);
        Mapper mapper = sqlSession.getMapper(clazz);
        return (T) MapperProxy.bind(mapper, sqlSession);
    }

    /**
     * 默认不提交事务的方法
     * @param clazz
     * @param dataSourceEnvironment
     * @param <T>
     * @return
     */
    public static <T> T createMapper(Class<? extends Mapper> clazz, DataSourceSessionFactory.DataSourceEnvironment dataSourceEnvironment) {
        return MapperFactory.createMapper(clazz, dataSourceEnvironment, false);
    }

    private static SqlSessionFactory getSqlSessionFactory(DataSourceSessionFactory.DataSourceEnvironment dataSourceEnvironment) {
        return DataSourceSessionFactory.getSessionFactory(dataSourceEnvironment);
    }

    private static class MapperProxy implements InvocationHandler {

        private Mapper mapper;
        private SqlSession sqlSession;

        private MapperProxy(Mapper mapper, SqlSession sqlSession) {
            this.mapper = mapper;
            this.sqlSession = sqlSession;
        }

        // 获取代理对象的实例 Java 只能代理接口
        public static Mapper bind(Mapper mapper, SqlSession sqlSession) {
            return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(), mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession));
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            try {
                result = method.invoke(mapper, args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                sqlSession.close();
            }

            return result;
        }
    }
}

测试方法

@Test
public void query() {
    UserMapper userMapper = MapperFactory.createMapper(UserMapper.class, DataSourceEnvironment.Spring);
    User user = userMapper.query("5f414d80-c413-42d4-8844-909d3e107ce8");
    System.out.println(user);
}

@Test
public void add() {
    UserMapper userMapper = MapperFactory.createMapper(UserMapper.class, DataSourceEnvironment.Spring, true);
    User user = new User(UUID.randomUUID().toString(), "XXX", "Second", "123456");
    int num = userMapper.add(user);
    System.out.println(num);
}

代码优化

以上的方式就可以支持多个数据源了,但是代码还不够优雅。以上代码,我们发现 DataSourceEnvironment 这个枚举变量在 Mapper 实现类以及 MapperFactory 中传来传去,我们应该尽量减少一个类对其他类的耦合,也就是上面的代码,不符合 Java 编程原则中的 迪米特法则 。

那我们来优化一下代码吧。

将 MapperFactory 设计成枚举策略模式,并且将 SqlSession 存放到 ThreadLocal 中,减少资源浪费:

package cn.worstone.utils;

import cn.worstone.mapper.Mapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Optional;

public enum MapperFactory {

    Spring {
        private SqlSessionFactory sqlSessionFactory;

        private final ThreadLocal<SqlSession> localSession = new ThreadLocal<>();

        @Override
        public <T> T createMapper(Class<? extends Mapper> clazz, boolean isCommit, boolean isClose) {
            return MapperFactory.createMapper(clazz, this, isCommit, isClose);
        }

        @Override
        public <T> T createAutoCommitMapper(Class<? extends Mapper> clazz) {
            return MapperFactory.createMapper(clazz, this, true, true);
        }

        @Override
        public <T> T createNotCloseMapper(Class<? extends Mapper> clazz) {
            return MapperFactory.createMapper(clazz, this, false, false);
        }

        @Override
        public <T> T createMapper(Class<? extends Mapper> clazz) {
            return this.createMapper(clazz, false, true);
        }

        @Override
        protected void createSqlSessionFactory() throws IOException {
            // 这个 I/O 流不用手动关, new SqlSessionFactoryBuilder().build() 里面已经关闭了这个流
            InputStream inputStream = Resources.getResourceAsStream(MapperFactory.MybatisConfigPath);
            this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name());
        }

        @Override
        protected void closeThreadLocal() {
            this.localSession.remove();
        }

        @Override
        public ThreadLocal<SqlSession> getThreadLocal() {
            return this.localSession;
        }

        @Override
        public SqlSessionFactory getSqlSessionFactory() {
            return this.sqlSessionFactory;
        }

        @Override
        public SqlSession getSqlSession() {
            return this.getSqlSession(false);
        }

        @Override
        public void closeSqlSession() {
            MapperFactory.closeSqlSession(this);
        }

        @Override
        public SqlSession getSqlSession(boolean isCommit) {
            return MapperFactory.getSqlSession(this, isCommit);
        }
    },
    Mybatis {
        private SqlSessionFactory sqlSessionFactory;

        private final ThreadLocal<SqlSession> localSession = new ThreadLocal<>();

        @Override
        public <T> T createMapper(Class<? extends Mapper> clazz, boolean isCommit, boolean isClose) {
            return MapperFactory.createMapper(clazz, this, isCommit, isClose);
        }

        @Override
        public <T> T createAutoCommitMapper(Class<? extends Mapper> clazz) {
            return MapperFactory.createMapper(clazz, this, true, true);
        }

        @Override
        public <T> T createNotCloseMapper(Class<? extends Mapper> clazz) {
            return MapperFactory.createMapper(clazz, this, false, false);
        }

        @Override
        public <T> T createMapper(Class<? extends Mapper> clazz) {
            return this.createMapper(clazz, false, true);
        }

        @Override
        protected void createSqlSessionFactory() throws IOException {
            InputStream inputStream = Resources.getResourceAsStream(MapperFactory.MybatisConfigPath);
            this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name());
        }

        @Override
        protected void closeThreadLocal() {
            this.localSession.remove();
        }

        @Override
        public ThreadLocal<SqlSession> getThreadLocal() {
            return this.localSession;
        }

        @Override
        public SqlSessionFactory getSqlSessionFactory() {
            return this.sqlSessionFactory;
        }

        @Override
        public SqlSession getSqlSession() {
            return this.getSqlSession(false);
        }

        @Override
        public void closeSqlSession() {
            MapperFactory.closeSqlSession(this);
        }

        @Override
        public SqlSession getSqlSession(boolean isCommit) {
            return MapperFactory.getSqlSession(this, isCommit);
        }
    };

    public abstract <T> T createMapper(Class<? extends Mapper> clazz, boolean isCommit, boolean isClose);

    public abstract <T> T createAutoCommitMapper(Class<? extends Mapper> clazz);

    public abstract <T> T createNotCloseMapper(Class<? extends Mapper> clazz);

    // 默认的 SqlSession 不提交事务, 而且调用一个方法后自动关闭
    public abstract <T> T createMapper(Class<? extends Mapper> clazz);

    protected abstract void createSqlSessionFactory() throws IOException;

    protected abstract void closeThreadLocal();

    public abstract ThreadLocal<SqlSession> getThreadLocal();

    public abstract SqlSessionFactory getSqlSessionFactory();

    public abstract SqlSession getSqlSession(boolean isCommit);

    public abstract SqlSession getSqlSession();

    public abstract void closeSqlSession();

    private static final String MybatisConfigPath = "mybatis.xml";

    static {
        try {
            MapperFactory.Mybatis.createSqlSessionFactory();
            MapperFactory.Spring.createSqlSessionFactory();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T createMapper(Class<? extends Mapper> clazz, MapperFactory mapperFactory, boolean isCommit, boolean isClose) {
        SqlSession sqlSession = mapperFactory.getSqlSession(isCommit);
        Mapper mapper = sqlSession.getMapper(clazz);
        if (isClose) {
            mapperFactory.closeThreadLocal();
        }
        return (T) MapperProxy.bind(mapper, sqlSession, isClose);
    }

    private static SqlSession getSqlSession(MapperFactory mapperFactory, boolean isCommit) {
        SqlSession sqlSession = mapperFactory.getThreadLocal().get();
        sqlSession = Optional.ofNullable(sqlSession).orElseGet(() -> {
            SqlSession temp = mapperFactory.getSqlSessionFactory().openSession(isCommit);
            mapperFactory.getThreadLocal().set(temp);
            return temp;
        });
        return sqlSession;
    }

    private static void closeSqlSession(MapperFactory mapperFactory) {
        SqlSession sqlSession = mapperFactory.getThreadLocal().get();
        if (sqlSession != null) {
            sqlSession.close();
        }
        mapperFactory.closeThreadLocal();
    }

    private static class MapperProxy implements InvocationHandler {

        private final Mapper mapper;
        private final SqlSession sqlSession;
        private final boolean isClose;

        private MapperProxy(Mapper mapper, SqlSession sqlSession, boolean isClose) {
            this.mapper = mapper;
            this.sqlSession = sqlSession;
            this.isClose = isClose;
        }

        // 获取代理对象的实例 Java 只能代理接口
        public static Mapper bind(Mapper mapper, SqlSession sqlSession, boolean isClose) {
            return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(), mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession, isClose));
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) {
            Object result = null;
            try {
                result = method.invoke(mapper, args);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 默认关闭, 可以手动设置不关闭
                if (isClose) {
                    sqlSession.close();
                }
            }

            return result;
        }
    }
}

测试方法

@Test
public void query() {
    UserMapper userMapper = MapperFactory.Spring.createMapper(UserMapper.class);
    User user = userMapper.query("5f414d80-c413-42d4-8844-909d3e107ce8");
    System.out.println(user);
}

@Test
public void add() {
    UserMapper userMapper = MapperFactory.Spring.createMapper(UserMapper.class, true);
    User user = new User(UUID.randomUUID().toString(), "XXX", "Second", "123456");
    int num = userMapper.add(user);
    System.out.println(num);
}

补充

对于复杂的事务可以采用如下方法进行控制:

SqlSession sqlSession = MapperFactory.Spring.getSqlSessionFactory().openSession(false);
try {
    // to do something
    // to do something
    sqlSession.commit();
} catch (Exception e) {
    sqlSession.rollback();
    e.printStackTrace();
} finally {
    if (sqlSession != null) {
        sqlSession.close();
    }
}

通过 new SqlSessionFactoryBuilder().build() 方法创建 SqlSessionFactory 时,不需要关闭参数中的 I/O 流,因为 build() 方法中已经将其关闭。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    SqlSessionFactory var5;
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        var5 = this.build(parser.parse());
    } catch (Exception var14) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
    } finally {
        ErrorContext.instance().reset();
        try {
            inputStream.close();
        } catch (IOException var13) {
        }
    }
    return var5;
}

Properties 属性类型的实现方式

思路:

  1. Mybatis 配置文件中 <environment> 标签设置为动态传参。
  2. DataSourceSessionFactory 类中构建 SqlSessionFactory 时,读取 DataBaseProperties 数据库配置类中的数据库连接信息动态生成。

Mybatis 配置信息:

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

DataBaseProperties 数据库配置类:

package cn.worstone.utils;

import java.util.Properties;

public class DataBaseProperties {

    public final static Properties Spring;

    public final static Properties Mybatis;

    static {
        Spring = new Properties();
        Spring.setProperty("driver", "com.mysql.cj.jdbc.Driver");
        Spring.setProperty("url", "jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC");
        Spring.setProperty("username", "root");
        Spring.setProperty("password", "123456");

        Mybatis = new Properties();
        Mybatis.setProperty("driver", "com.mysql.cj.jdbc.Driver");
        Mybatis.setProperty("url", "jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC");
        Mybatis.setProperty("username", "root");
        Mybatis.setProperty("password", "123456");
    }
}

DataSourceSessionFactory 类以及测试方法:

package cn.worstone.utils;

import cn.worstone.bean.User;
import cn.worstone.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public final class DataSourceSessionFactory {

    private static String MybatisConfigPath = "mybatis.xml";
    private static Map<Properties, SqlSessionFactory> sessionFactoryMap = new HashMap<>();

    public static SqlSessionFactory getSessionFactory(Properties dataSourceProperties) {
        SqlSessionFactory sqlSessionFactory = DataSourceSessionFactory.sessionFactoryMap.get(dataSourceProperties);
        sqlSessionFactory = Optional.ofNullable(sqlSessionFactory).orElseGet(()->{
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream(DataSourceSessionFactory.MybatisConfigPath);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new SqlSessionFactoryBuilder().build(inputStream, dataSourceProperties);
        });

        sessionFactoryMap.put(dataSourceProperties, sqlSessionFactory);
        return sqlSessionFactory;
    }

    public static void main(String[] args) {
        SqlSession sqlSession = DataSourceSessionFactory.getSessionFactory(DataBaseProperties.Spring).openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.queryList();
        sqlSession.close();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

参考资料:

MyBatis多数据源配置及动态切换——搭建多个数据源并动态切换 随着互联网的发展、移动互联网的兴起和需求的增加,网站应用的规模也越来越庞大。由于业务不同,每个站点会存在不同的数据库,所以在同一个系统中,需要配置多个数据库连接。而 MyBatis 是目前主流的开源持久层框架之一,它的多数据源支持就显得尤为重要。本文将详细介绍 MyBatis 的多数据源配置及动态切换,并结合实际案例实现三个数据库的动态切换。MyBatis 是一款优秀的持久层框架,它可以很方便地通过简单的 XML 或注解的方式来完成对数据库的操作。 阅读详情

相关推荐

发票OFD格式转换成PDF

发票OFD格式转换成PDF

Be_insighted的博客 934

SpringBoot Mybatis多数据源配置

⏹SpringBoot Mybatis多数据源配置

菜鸟记录 1万+

5分钟搞定PaddleOCR PP-OCRv5环境搭建:从安装到第一个识别Demo

本文提供了一份详细的PaddleOCR PP-OCRv5环境搭建与快速入门指南。通过清晰的步骤,指导读者在5分钟内完成从创建Python虚拟环境、安装PaddlePaddle框架和PaddleOCR库,到编写并运行第一个OCR识别Demo的全过程,帮助开发者快速体验最新的PP-OCRv5模型的文字识别能力。

sprite的博客 1271

Mybatis配置多数据源

Spring Boot项目使用Mybatis,既要从上游系统同步数据,又要操作本系统的数据库,所以需要引入双数据源,配置Mybatis。

weixin_44385360的博客 1万+

c++通过自然语言处理技术分析语音信号音高

其中,缓冲区大小为2048,最小基频为80Hz,最大基频为1000Hz。通常情况下,音高在85Hz到255Hz之间,因此可以根据实际情况修改最小和最大基频值。C++中可以使用数字信号处理库或语音处理库,比如MATLAB、Praat、YIN算法等等来进行音高分析。对于语音信号的音高分析,可以使用基频提取技术。基频是指一个声音周期的重复率,也就是一个声音波形中最长的周期。通常情况下,人的声音基频范围是85Hz到255Hz。这段代码使用了YIN算法来计算语音信号的基频,得出的结果即为音高。

SYC20110120的博客 1729

业态即战场:零售平台的生意模型与系统设计解构

在这篇文章中,我们从“控货、自营、联营”三种典型零售业态出发,拆解了亚马逊、阿里、京东和本地闪购平台在商品模型设计上的差异与博弈。看似简单的卖货方式背后,其实是平台在“控货权”“商品归属权”上的深层策略博弈:谁掌控商品,谁就掌控数据、流量与利润分配权。本文尝试用一套通俗但不失专业的方式,帮助产品经理和技术伙伴读懂零售平台商品模型的底层逻辑与系统设计演化路径。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 13万+

mybatis多数据源

1,简介 在实际开发中很容易就遇到需要多数据源的情形,比如说,在新增数据时除了给自己的库保留一份,还需要同步到别人的库;转移程序需要将A库的数据转到B库等等。使用mybatis配置多数据源我接触过的一般有两种方式,一种是通过java config的方式手动配置两个数据源,另一种方式便是使用mybatis-plus-dynamic。 2,具体使用 2.1 手动配置多个数据源 2.1.1 代码示例 项目基于springboot和mybatis-plus,首先引入相应的依赖: <?xml ve

qq_38353700的博客 2万+

innovus:Patch Wire(补丁线)

1)选中wire ,shift+A使用Edit Route功能,F3打开edit route对话框。线道Create Patch Wire,设置好层次和宽度。在修补一些min area的drc时,会有一些danling wire的drc冒出来,为了避免这些假错,可以使用工具patch wire功能。2)沿着选中的wire画线即可。如下图,patch wire和regular wire是能看出区别的。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 1967

Mybatis中配置多个数据源的两种实现方式

需求描述 在我们的开发过程中,一个项目连接多个数据库经常出现。在Spring+Mybatis的项目中,遇到这种情况该怎么办? 我整理了一下,基本上两种方式去解决。 配置多个sqlSessionFactory 配置多个数据源使用AOP切换 配置多个sqlSessionFactory的方式实现多数据源配置 这种方式是比较简单的,在xml中,配置多个sqlSessionFactor...

yyf的博客 1万+

Carla中如何渲染opendrive车道线和车道标识(全网独家,附代码)

carla是可以单独加载opendrive并渲染路面的,但是无法把车道线渲染出来,这是一个大坑,因为没有车道线就无法给感知输入。楼主已经实现,直接渲染车道线或者带PBR贴图的车道标识。实现起来非常简单,但必须对carla源码以及ue的开发足够了解。在carla源码中有一个很重要的类opendrivegenerator,它是关于opendrive渲染的全部方法,但是你是找不到它实例化的地方的,因为它被定义在蓝图关卡中。网上包括carla官方关于carla源码的分析少之又少,楼主将自己的经验写出来供大家参考。

u013998156的博客 1094

HFSS实战项目——GPS北斗双模微带天线

本文设计了一款方形圆极化微带天线应用于北斗B1和GPSL1频段,满足高增益、低VSWR、适当方向图等要求。设计中心频率为1568MHz,介质板采用厚度h=1.6mm的Arlon AD450(tm)板,相对介电常数为4.5,采用探针馈电。

2401_87464239的博客 1769

Spring4 Mybatis配置多个数据源

Spring4 Mybatis配置多个数据源 概要 在实际项目当中,会使用多个数据源,比如replication结构, 或者基表库和用户库等等。 配置多个数据源有很多方式, 在这里只记载用annotation方式的多个数据源配置方式给记录下来。 方便以后再来这边做拷贝。 配置 版本,依赖 dependencies { compile 'org.springfr...

kimsung的专栏 1243

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SpringBoot项目如何使用Mybatis连接多个数据源

SpringBoot项目如何使用Mybatis连接多个数据源 1 说明 在SpringBoot项目中使用Mybatis访问数据库非常方便,同时也支持访问多个数据源,有一种实现方式是 分包实现,就是将不同数据源生成的mybatis接口类、xml映射文件、pojo文件放到不同的package里面,以此实现 互不干扰,独立使用的目的,下面分享一下我的使用经验。 2 步骤 2.1 多数据库连接配置 在yml文件中配置多个数据库连接: spring: #mysql数据库配置 mysqldatasource:

猿经验(yuanjingyan.com) 859

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

SpringBoot配置JPA和mybatis双数据源

JPA配置为spring.datasource前缀,mybatis为spring.datasource.eps开头 1.创建DataSourceConfig配置类,来定义数据源 其实 @Primary表示默认,如果使用了JPA则默认使用该数据源 package com.xinyuan.core.config; import org.springframework.beans.fa...

不二雄的博客 6955

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

SpringBoot和Mybatis配置多数据源连接多个数据库

前业界操作数据库的框架一般是 Mybatis,但在很多业务场景下,我们需要在一个工程里配置多个数据源来实现业务逻辑。在SpringBoot中也可以实现多数据源并配合Mybatis框架编写xml文件来执行SQL。在SpringBoot中,配置多数据源的方式十分便捷, 下面开始上代码: 在pom.xml文件中需要添加一些依赖 <!-- Spring Boot Mybatis 依赖 --> <dependency> <groupId>org.mybatis.spring.b

ytitsjh的博客 1923

SpringBoot集成mybatis使用durid多数据源配置

SpringBoot集成mybatis自定义多数据源配置 1.首先配置application.yml。 因为spring官方没有提供和durid集成,所以这部分也需要自定义配置。 datasource: local: url: jdbc:mysql://127.0.0.1:3306/my_dev?autoReconnect=true&amp;amp;useUnicode=true...

Jagger的博客 6409

springboot 整合mybatis多数据源以及出现的问题

一、整合mybatis多数据源 工程结构目录 1.pom.xml文件里加入 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>...

weixin_37704921的博客 1317

多数据源配置-使用spring配置多个数据源实现读写分离

我们在很多的项目中经常会有用到多个数据源。比如数据库读写分离,读操作都去从库里读,写操作都往主库里写。那么这里主库和从库就是两个不同的数据源。再比如要做两个数据库之间的数据转换,从一个数据库读取数据写到另一个数据库中,等等这些情况都需要系统使用两个或多个数据源。那么该如何配置多个数据源呢?我这里使用的是spring管理,数据库连接池使用的是阿里的druid。具体步骤如下: 1.修改spring的配...

chinadim的专栏 500

SpringBoot多数据源配置详细教程

文章概要 简单多数据配置 JdbcTemplate 多数据源配置 mybatis多数据源配置 mybatis-plus多数据源配置 多数据源配置 首先是配置文件 spring: # 数据源配置 datasource: ds1: #数据源1 driver-class-name: com.mysql.jdbc.Driver # mysql的驱动你可以配置别的关系型数据库 url: jdbc:mysql://ip:3306/db1 #数据源地址 use

Hanko的专栏 355

Spring配置多数据源实战

Spring配置多数据源实战 这里我们只演示同一个mysql下面的不同的两个库,主要采取分包的形式来区分不同的数据源: Spring的xml方式配置多数据源: DBConfig1: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-in...

城南少年与猫 260

springboot+mybatis配置动态数据源

springboot mybatis 动态数据源

jdbcmeng的博客 3172

Mybatis+Druid+MybatisPlus多数据源配置

平常我们使用的是 properties 或者 yaml 来配置数据库的地址、用户名、密码等,但是这样只能配置一个数据源,现在我们想在一个项目里面配置多个数据源,那么我们就需要配置自己的配置类

我认不到你的博客 1548

mysql 配置多个数据库连接_SpringBoot和Mybatis配置多数据源连接多个数据库

目前业界操作数据库的框架一般是Mybatis,但在很多业务场景下,我们需要在一个工程里配置多个数据源来实现业务逻辑。在SpringBoot中也可以实现多数据源并配合Mybatis框架编写xml文件来执行SQL。在SpringBoot中,配置多数据源的方式十分便捷,下面开始上代码:在pom.xml文件中需要添加一些依赖org.mybatis.spring.bootmybatis-spring-bo...

weixin_27717759的博客 370

SpringBoot mybatis 拦截器配置读写分离

SpringBoot mybatis 拦截器配置读写分离 上一篇mysql 在linux 下配置 主从复制,这一篇代码层实现读写分离 实现方式有很多,但是不外乎分为内部配置和使用中间件,下面列举几个常用的方法: 1.配置多个数据源,根据业务需求访问不同的数据,指定对应的策略:增加,删除,修改操作访问 对应数据,查询访问对应数据,不同数据库做好的数据一致性的处理。由于此方法相对易懂,简单, 不做...

weixin_43791528的博客 1289
上一篇: MyBatis 相关概念
下一篇: Spring Boot
LiveForCode
博客等级 码龄5年 2粉丝 16原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值