springboot mybatis和spark-sql、SDB对接_mybatis 执行 sparksql-程序员宅基地

技术标签: spring  Sequoiadb学习笔记  java  数据库  

springboot mybatis和spark-sql对接

本次将在已经部署了spark、hive和SequoiaDB的环境中,通过实验来实现springboot、mybatis框架与spark-sql的整合,通过hive-sql实现spark的鉴权和权限控制,并能够通过springboot、mybatis访问spark查询SequoiaDB中的数据,具体部署环境为下:

jdk1.8 spark2.1.1 hadoop2.9.2 hive1.2.2

本次实验SequoiaDB巨杉数据库集群拓仆结构为三分区单副本,其中包括:
  • 1 个 SequoiaSQL-MySQL 数据库实例节点
  • 1 个引擎协调节点
  • 1 个编目节点
  • 3 个数据节点
本次实验分为下列步骤:
  • 使用MySQL配置hive元数据库
  • hive配置部分,需正确配置hive-site.xml配置文件中连接mysql的jdbc配置以及开启鉴权功能
  • 元数据库的初始化
  • 配置spark连接metastore以及开启鉴权功能
  • 添加测试数据
  • 配置IDEA项目
  • 调用方法进行测试

使用MySQL配置hive元数据库
使用sdbadmin用户进入mysql-shell:
su sdbadmin
/opt/sequoiasql/mysql/bin/mysql -h 127.0.0.1 -P 3306 -u root
创建metauser用户,用于后续hive以及spark连接元数据库:
CREATE USER 'metauser'@'%' IDENTIFIED BY 'metauser';
给metauser用户授权:
GRANT ALL ON *.* TO 'metauser'@'%';
创建元数据库metastore:
CREATE DATABASE metastore CHARACTER SET 'latin1' COLLATE 'latin1_bin';
刷新权限:
FLUSH PRIVILEGES;
退出mysql-shell:
quit;

hive配置部分
复制以下代码到实验环境终端执行,用于添加hive元数据信息的数据库配置文件hive-site.xml到${HIVE_HOME}/conf目录下,并正确配置:
cat > /opt/apache-hive-1.2.2-bin/conf/hive-site.xml<< EOF
<configuration>
   <property>
     <name>javax.jdo.option.ConnectionURL</name>
     <value>jdbc:mysql://localhost/metastore?createDatabaseIfNotExist=true</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionDriverName</name>
     <value>com.mysql.jdbc.Driver</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionUserName</name>
     <value>metauser</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionPassword</name>
     <value>metauser</value>
   </property>
   <property>
      <name>hive.test.authz.sstd.hs2.mode</name>
      <value>true</value>
   </property>
   <property>
      <name>hive.server2.enable.doAs</name>
      <value>true</value>
   </property>
   <property>
      <name>hive.users.in.admin.role</name>
      <value>root</value>
   </property>
   <property>
      <name>hive.server2.thrift.port</name>
      <value>9073</value>
   </property>
   <property>
     <name>hive.server2.authentication</name>
     <value>CUSTOM</value>
   </property>
   <property>
     <name>hive.server2.custom.authentication.class</name>
     <value>com.sequoiadb.spark.sql.hive.SequoiadbAuth</value>
   </property>
   <property>
      <name>hive.security.authorization.manager</name>
      <value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value>
   </property>
</configuration>
EOF
拷贝依赖jar到${HIVE_HOME}/auxlib(第三方jar包目录)目录下,如果auxlib目录不存在,则自行创建:
cp spark-authorizer-2.1.1.jar /opt/apache-hive-1.2.2-bin/auxlib
cp mysql-connector-java-5.1.7-bin.jar /opt/apache-hive-1.2.2-bin/auxlib

元数据库metastore初始化配置
修改${HIVE_HOME}/conf/hive-env.sh,添加以下代码(本次实验hadoop安装在/opt下,可根据用户情况自行修改),本次实验hive-env位置为:/opt/apache-hive-1.2.2-bin/conf/hive-env.sh
export HADOOP_HOME=/opt/hadoop-2.9.2
使用hive1.2.2软件上提供的schematool工具初始化metastore,${HIVE_HOME}/bin/schematool -dbType mysql -initSchema
apache-hive-1.2.2-bin/bin/schematool -dbType mysql -initSchema

结果截图

使用sdbadmin用户进入mysql-shell,在metastore database中,创建一个USER表,表名称为DBUSER:
su sdbadmin
/opt/sequoiasql/mysql/bin/mysql -h 127.0.0.1 -P 3306 -u root
use metastore;
create table DBUSER (dbuser varchar(100), passwd char(50), primary key (dbuser));
insert into DBUSER(dbuser, passwd) values ('root', md5('admin'));

为 thrift server 预先创建了一个 root 的用户,密码为 ‘admin’ 未来如果要增加用户,用类似的 insert 命令添加

对metastore库下的DBS表创建触发器(目的是为了让用户可以跨库create table as,当用户在sparksql create database时,触发器自动对DBS表的OWNER_NAME,OWNER_TYPE两个字段进行更新):
delimiter ||
create trigger  dbs_trigger
before insert on DBS
for each row
begin
set new.OWNER_NAME="public";
set new.OWNER_TYPE="ROLE";
end  ||

delimiter ;

spark配置:
spark sql 增加鉴权和权限管理,需添加依赖jar包到${SPARK_HOME}/jars(本次实验spark安装目录为/opt/spark/)
cp spark-authorizer-2.1.1.jar /opt/spark/jars
cp mysql-connector-java-5.1.7-bin.jar /opt/spark/jars
复制以下代码到实验环境终端执行,用于添加hive元数据信息的数据库配置文件hive-site.xml到${SPARK_HOME}/conf目录下,并正确配置:
cat > /opt/spark/conf/hive-site.xml<< EOF

<configuration>
   <property>
     <name>javax.jdo.option.ConnectionURL</name>
     <value>jdbc:mysql://localhost/metastore?createDatabaseIfNotExist=true</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionDriverName</name>
     <value>com.mysql.jdbc.Driver</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionUserName</name>
     <value>metauser</value>
   </property>
   <property>
     <name>javax.jdo.option.ConnectionPassword</name>
     <value>metauser</value>
   </property>
   <property>
        <name>hive.security.authorization.createtable.owner.grants</name>
        <value>INSERT,SELECT</value>
   </property>
   <property>
       <name>hive.security.authorization.enabled</name>
       <value>true</value>
   </property>
   <property>
       <name>hive.security.authorization.manager</name>
       <value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value>
   </property>

   <property>
      <name>hive.test.authz.sstd.hs2.mode</name>
      <value>true</value>
   </property>

   <property>
      <name>hive.server2.authentication</name>
      <value>CUSTOM</value>
   </property>
   <property>
      <name>hive.server2.custom.authentication.class</name>
      <value>com.sequoiadb.spark.sql.hive.SequoiadbAuth</value>
   </property>
</configuration>

EOF
在 ${SPARK_HOME}/conf/spark-defaults.conf 配置文件中,增加以下内容
spark.sql.extensions=org.apache.ranger.authorization.spark.authorizer.SequoiadbSparkSQLExtension
启动spark:
./opt/spark/sbin/start-all.sh
启动thriftserver服务:
./opt/spark/sbin/start-thriftserver.sh
查看端口监听状态:
netstat -anp|grep 10000
使用spark自带的beeline客户端工具连接到thriftserver服务(默认端口10000):
./bin/beeline -u jdbc:hive2://localhost:10000 -n root -p admin

在 spark sql 中创建数据表,执行建表的USER 对该表拥有 INSERT 和 SELECT 权限 如果其他 USER希望访问该表,应该在 hive 的thrift server 中,执行 grant 命令,以赋予其他 USER 对应权限

操作方式:
启动hive的thrift服务
${HIVE_HOME}/bin/hiveserver2 >${HIVE_HOME}/hive_thriftserver.log 2>&1 &
通过hive自己的beeline连接到hive-site.xml配置的(hive.server2.thrift.port)接口中,使用root登录以及密码为admin(在上述中mysql对DBUSER表插入的用户)
进入到${HIVE_HOME},输入下面代码:
./bin/beeline -u jdbc:hive2://localhost:9073 -n root -p admin
权限控制:
set role admin;
grant SELECT on table test to user USERNAME;
grant INSERT on table test to user USERNAME;

添加测试数据
在SequoiaDB中创建域和集合空间:
var db=new Sdb("localhost",11810);

db.createDomain("scottdomain",["datagroup1","datagroup2","datagroup3"],{
    AutoSplit:true});

db.createCS("scott",{
    Domain:"scottdomain"});

在MySQL中创建测试表以及数据:
使用sdbadmin用户登录到mysql-shell中:
/opt/sequoiasql/mysql/bin/mysql -h 127.0.0.1 -P 3306 -u root
创建数据库:
create database scott;

use scott;
创建表emp(另外三张表同理):
create table emp(
    empno           int unsigned auto_increment primary key COMMENT '雇员编号',
    ename           varchar(15) COMMENT '雇员姓名',
    job             varchar(10) COMMENT '雇员职位',
    mgr             int unsigned COMMENT '雇员对应的领导的编号',
    hiredate        date COMMENT '雇员的雇佣日期',
    sal             decimal(7,2) COMMENT '雇员的基本工资',
    comm            decimal(7,2) COMMENT '奖金',
    deptno          int unsigned COMMENT '所在部门'

)ENGINE = sequoiadb COMMENT = "雇员表, sequoiadb: { table_options: { ShardingKey: { 'empno': 1 }, ShardingType: 'hash', 'Compressed': true, 'CompressionType': 'lzw', 'AutoSplit': true, 'EnsureShardingIndex': false } }";
并添加测试数据到emp表中:
INSERT INTO emp VALUES    (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES    (7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30);
INSERT INTO emp VALUES    (7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30);
INSERT INTO emp VALUES    (7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20);
INSERT INTO emp VALUES    (7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250,1400,30);
INSERT INTO emp VALUES    (7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30);
INSERT INTO emp VALUES    (7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10);
INSERT INTO emp VALUES    (7788,'SCOTT','ANALYST',7566,'87-7-13',3000,NULL,20);
INSERT INTO emp VALUES    (7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES    (7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,100,30);
INSERT INTO emp VALUES    (7876,'ADAMS','CLERK',7788,'87-7-13',1100,NULL,20);
INSERT INTO emp VALUES    (7900,'JAMES','CLERK',7698,'1981-12-3',950,NULL,30);
INSERT INTO emp VALUES    (7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20);
INSERT INTO emp VALUES    (7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10);

配置IDEA项目
springboot mybatis和spark sql对接部分:
项目结构:

项目结构

在maven项目pom.xml文件中添加以下依赖:
<!--添加druid连接池依赖-->
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.58</version>
 </dependency>
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid-spring-boot-starter</artifactId>
     <version>1.1.18</version>
 </dependency>
 <!-- mybatis依赖 -->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-core</artifactId>
     <version>${mybatis-plus.version}</version>
 </dependency>
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-extension</artifactId>
     <version>${mybatis-plus.version}</version>
 </dependency>
<!--添加 spark通过jdbc连接的依赖包-->
 <dependency>
     <groupId>commons-logging</groupId>
     <artifactId>commons-logging</artifactId>
     <version>1.1.3</version>
 </dependency>
 <dependency>
     <groupId>org.apache.hive</groupId>
     <artifactId>hive-exec</artifactId>
     <version>1.2.1</version>
 </dependency>
 <dependency>
     <groupId>org.apache.hive</groupId>
     <artifactId>hive-metastore</artifactId>
     <version>1.2.1</version>
 </dependency>
 <dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpclient</artifactId>
     <version>4.5.2</version>
 </dependency>
 <dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpcore</artifactId>
     <version>4.4.4</version>
 </dependency>
 <dependency>
     <groupId>org.apache.thrift</groupId>
     <artifactId>libthrift</artifactId>
     <version>0.9.2</version>
 </dependency>
 <dependency>
     <groupId>log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>1.2.17</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.7.10</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-log4j12</artifactId>
     <version>1.7.10</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-hive-thriftserver -->
 <dependency>
     <groupId>org.apache.spark</groupId>
     <artifactId>spark-hive-thriftserver_2.11</artifactId>
     <version>2.0.1</version>
     <scope>provided</scope>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-network-common -->
 <dependency>
     <groupId>org.apache.spark</groupId>
     <artifactId>spark-network-common_2.11</artifactId>
     <version>2.0.1</version>
 </dependency>


<!--添加SequoiaDB驱动包-->
 <dependency>
     <groupId>com.sequoiadb</groupId>
     <artifactId>sequoiadb-driver</artifactId>
     <version>3.2.1</version>
 </dependency>
<!--添加SequoiaDB和spark连接驱动包-->
<dependency>
     <groupId>com.sequoiadb</groupId>
     <artifactId>spark-sequoiadb_2.11</artifactId>
     <version>2.8.0</version>
 </dependency>
 <dependency>
     <groupId>com.sequoiadb</groupId>
     <artifactId>spark-sequoiadb-scala_2.11.2</artifactId>
     <version>1.12</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql -->
 <dependency>
     <groupId>org.apache.spark</groupId>
     <artifactId>spark-sql_2.11</artifactId>
     <version>2.2.2</version>
 </dependency>
<!--添加hive jdbc连接组件-->
 <dependency>
     <groupId>org.apache.hive</groupId>
     <artifactId>hive-jdbc</artifactId>
     <version>1.2.1</version>
 </dependency>
 <dependency>
     <groupId>org.apache.hadoop</groupId>
     <artifactId>hadoop-common</artifactId>
     <version>3.2.0</version>
 </dependency>
在application.properties配置文件中,添加如下配置:
server.port=8090

#datasource config
#指定连接池类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#指定驱动
spring.datasource.driver-class-name=org.apache.hive.jdbc.HiveDriver
#指定连接地址、用户名和密码
spring.datasource.url=jdbc:hive2://192.168.80.132:10000/default
spring.datasource.username=root
spring.datasource.password=admin

#初始化连接数量
spring.datasource.druid.initialSize=1
#最大空闲连接数
spring.datasource.druid.minIdle=5
#最大并发连接数
spring.datasource.druid.maxActive=20
#配置获取连接等待超时的时间
spring.datasource.druid.maxWait=60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.timeBetweenEvictionRunMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.minEvictableIdelTimeMillis=300000
#用来检测连接是否有效的sql,要求是一个查询语句
spring.datasource.druid.validation-query=SELECT 1
#mybatis
#mybatis-plus.mapper-locations=classpath:mapper/*.xml
#mybatis-plus.configuration.cache-enabled=false
#映射xml文件位置
mybatis.mapper-locations=classpath:mapper/*.xml
#需要扫描实体类的位置
mybatis.type-aliases-package=com.sdb.spark.demo.entity
#spring mvc配置静态文件
spring.mvc.static-path-pattern=/static/**
#热部署
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=src/main/java
spring.devtools.restart.exclude=WEB-INF/**
在com.sdb.spark.demo.entity包中配置emp实体类Emp:
/**
 * 雇员表
 *
 * @author yousongxian
 * @date 2020-07-29
 */
public class Emp {
    
    private Integer empno;//雇员编号
    private String ename;//雇员姓名、
    private String job;//雇员职位
    private Integer mgr;//雇员对应的领导的编号
    private String hiredate;//雇员的雇佣日期
    private Double sal;//雇员的基本工资
    private Double comm;//奖金
    private Integer deptno;//所在部门
    }
    //省略getter和setter方法
    @Override
    public String toString() {
    
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate='" + hiredate + '\'' +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                '}';
    }
在classpath:resources下创建新文件夹mapper,并新建mybatis实体类映射文件EmpMapper.xml(映射Emp)
在EmpMapper.xml文件中新增通用查询映射结果(column对应创建表时候定义的字段名,property对应实体类中的属性名称):
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.sdb.spark.demo.entity.Emp">
    <id column="empno" property="empno"/>
    <result column="ename" property="ename" />
    <result column="job" property="job" />
    <result column="mgr" property="mgr" />
    <result column="hiredate" property="hiredate" />
    <result column="sal" property="sal" />
    <result column="comm" property="comm" />
    <result column="deptno" property="deptno" />
</resultMap>
在EmpMapper.xml中新增查询全部的方法,返回类型为map
<!-- 通用查询结果列 -->
<select id="selectAll" resultType="map" parameterType="string">
     select * from ${tablename}
</select>
在EmpMapper.xml中新增创建表tmp的方法(第一种)
<update id="createTableEmp">
 CREATE TABLE emp
(
empno  INT,
ename  STRING,
job  STRING,
mgr  INT,
hiredate  date,
sal  decimal(7,2),
comm  decimal(7,2),
deptno    INT
)
USING com.sequoiadb.spark OPTIONS
(
host 'localhost:11810',
collectionspace 'scott',
collection 'emp'
)</update>
在EmpMapper.xml中新增创建表tmp_schema的方法(第二种:使用连接器自动生成SCHEMA),要求在建表时 SequoiaDB 的关联集合中就已经存在数据记录
<update id="createTableEmpSchema">
CREATE TABLE emp_schema USING com.sequoiadb.spark OPTIONS
(
host 'localhost:11810',
collectionspace 'scott',
collection 'emp'
  )
</update>
在EmpMapper.xml中新增创建表tmp_as_select的方法,输入参数为map类型(第三种:通过 SQL 结果集创建表)
<update id="createTableAsSelect" parameterType="map">
CREATE TABLE ${tablename} USING com.sequoiadb.spark OPTIONS
(
host 'localhost:11810',
domain 'scottdomain',
collectionspace 'scott',
collection #{tablename},
shardingkey '{"_id":1}',
shadingtype 'hash',
autosplit true
)AS ${condition}
</update>
在EmpMapper.xml最上方标签内添加namespace属性,这里指定namespace=“com.sdb.spark.demo.mapper.EmpMapper”,意思是EmpMapper.xml内定义的方法映射接口为com.sdb.spark.demo.mapper包下的EmpMapper接口文件
<mapper namespace="com.sdb.spark.demo.mapper.EmpMapper">
在com.sdb.spark.demo.mapper中配置EmpMapper接口文件,并根据在EmpMapper.xml中定义的方法id以及输入、输出类型创建方法(EmpMapper.xml文件中定义的update类型方法默认返回值为操作影响的行数(int)):

注意:方法名称跟xml映射文件中定义的方法id必须一致

List<Map<String,Object>> selectAll(String tablename);//查询全部

int createTableEmp();//创建emp表

int createTableEmpSchema();//用自动生成schema的方式创建emp_schema表

int createTableAsSelect(Map<String,String>map);//用查询结果创建emp_as_select表

int insertEmp(Emp emp);//对emp插入记录
com.sdb.spark.demo.service中配置EmpService接口并定义以下方法:
List<Map<String,Object>> selectAll(String tablename);

int createTableEmp();

int createTableEmpSchema();//用自动生成schema的方式创建emp_schema表

int createTableAsSelect(Map<String,String> map);//用查询结果创建emp_as_select表

int insertEmp(Emp emp);//对emp插入记录
com.sdb.spark.demo.service.Impl中创建EmpServiceImpl类并实现EmpService接口,并在类上方添加@service注解:
@Service
public class EmpServiceImpl implements EmpService {
    

    @Autowired
    private EmpMapper empMapper;


    @Override
    public List<Map<String,Object>> selectAll(String tablename) {
    
        return empMapper.selectAll(tablename);
    }

    @Override
    public int createTableEmp() {
    
        return empMapper.createTableEmp();
    }

    @Override
    public int createTableEmpSchema() {
    
        return empMapper.createTableEmpSchema();
    }

    @Override
    public int createTableAsSelect(Map<String,String>map) {
    
        return empMapper.createTableAsSelect(map);
    }

    @Override
    public int insertEmp(Emp emp) {
    
        return empMapper.insertEmp(emp);
    }

}

在测试类调用方法部分:
在classpath:test.java.com.sdb.spark.demo.DemoApplicationTests测试类下,添加以下代码,用于调用EmpService实现类中的方法
定义EmpService类型的变量,并添加注解@Autowired实现自动注入:
@Autowired
private EmpService empService;
定义方法selectAll用于查询全部,并在方法上添加junit注解@Test用于测试:
@Test
public List<Map<String,Object>> selectAll(){
    
    String tablename="emp";
    List<Map<String,Object>>resultlist=new ArrayList<Map<String, Object>>();
    resultlist =empService.selectAll(tablename);

    for(Map<String,Object>map:resultlist){
    
        for(Map.Entry<String,Object>m:map.entrySet()){
    
            System.out.print(m.getKey()+"="+m.getValue()+"\t");
        }
        System.out.println();
    }
    return resultlist;
}
定义三种创建表的方法,并各自在方法上添加junit注解@Test用于测试:
@Test
public void createTable(){
    
   empService.createTableEmp();
}

@Test
public void createTableEmpSchema(){
    
    empService.createTableEmpSchema();
}

@Test
public void createTableAsSelect(){
    
    Map<String,String> map=new HashMap<String, String>();
    String tablename="emp_as_select";
    //String condition="select empno,ename from emp";
    map.put("tablename",tablename);
    map.put("condition",condition);
 if(map.get("tablename").equals("")||map.get("tablename")==null||map.get("condition").equals("")||map.get("condition")==null){
    
        System.out.println("请输入正确表明和条件");
    }else {
    
        empService.createTableAsSelect(map);
    }
}
在springboot启动类DemoApplication的类名上方,添加spring扫描注解,具体类配置如下:
@SpringBootApplication(scanBasePackages = {
    "com.sdb.spark.demo.service.Impl"})
@MapperScan(basePackages = {
    "com.sdb.spark.demo.mapper"})
public class DemoApplication {
    

    public static void main(String[] args) {
    
        SpringApplication.run(DemoApplication.class, args);
    }

}
启动DemoApplication类
调用DemoApplicationTests测试类下方法进行测试
三种方式创建表后,修改selectAll()方法中的tablename进行查询
结果截图:

结果截图

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40207018/article/details/107791107

智能推荐

ESP8266和ESP32区别,以及优缺点分析!_esp8266为什么不建议使用-程序员宅基地

文章浏览阅读3.4k次,点赞3次,收藏4次。高速主频240MHZ,对比STM32F1的72MHZ和STM32F4的168MHZ,速度快很多,而且价格上比起一直在涨价的STM系低出非常多;总的来说,STM32在国内的使用程度和受众程度是远大于ESP32的,毕竟STM32已经占据主流市场很久了,学习的资料比起ESP32起来会多,再加上一些开源问题,使用32的人群还是占据多数。2016年,乐鑫推出了ESP32,它是ESP8266的升级版本,速度更快还带有蓝牙4.2和蓝牙低功耗,价格在20元左右,在这个价格下几乎找不到对手可以“一战”。_esp8266为什么不建议使用

linux 分区简介,Linux硬盘分区知识简介-程序员宅基地

文章浏览阅读990次。Linux系统可以挂载多个不同接口类型的磁盘(disk),每一个磁盘又可以分成若干个分区(Partition),每个分区又可以拥有自己的文件系统类型(FileSystem)。Linux对于磁盘和分区又自己的一套标记方法。硬盘和分区的区分第一个SCSI(Small Computer System Interface)磁盘记为/dev/sda,第二个SCSI磁盘记为/dev/sdb;第一个SATA磁盘..._linux引导分区的标记可为

unity 网络游戏架构设计(第12课:网络游戏案例讲解)之美_网络游戏消息结构设计案例-程序员宅基地

文章浏览阅读656次。第12课:网络游戏案例讲解上章给读者介绍关于服务器之间的通信,本章通过案例给读者介绍如何将框架跟 Photon 结合起来,实现一个网络通信的框架设计。UI 架构设计模块已经介绍过,我们的 Demo 使用的 UI 是 UGUI,简单的用几个 Button 代替 Sprite,它们的原理是一样的。我们先创建一个 UI,如下图所示:这个 UI 主要有三个关键按钮,分别是 Create Roo..._网络游戏消息结构设计案例

Android-Gradle详解_grade编译运行安卓-程序员宅基地

文章浏览阅读548次。Android 构建系统非常灵活,可让你在不修改应用核心源代码文件的情况下执行自定义构建配置。本部分将介绍 Android 构建系统的工作原理,以及它如何帮助你对多个构建配置进行自定义和自动化处理。构建过程涉及许多将你的项目转换为 Android 应用程序包 (APK) 的工具和过程。构建过程非常灵活,因此了解一些幕后发生的事情很有用。下图为Android 应用模块的构建过程。Android 应用模块的构建过程(如上图所示)遵循以下一般步骤:1、编译器将你的源代码转换为 DEX(Dalv_grade编译运行安卓

linux网络配置后面加一条wheel,linux安全配置/etc/sudoers&wheel组-程序员宅基地

文章浏览阅读800次。/etc/sudoers 控制哪些用户能在哪些主机上以哪些用户的身份执行哪些命令。只有此文件权限为440时才能用户才能使用sudo命令,只有root用户才能使用visudo命令修改此文件。当然也可以先添加文件写权限,然后修改,再把文件权限改回来。此文件的一些配置规则定义别名:User_Alias UserName = user1,user2,kongoveHost_Alias HostName =..._%wheel all=(all) all

NO.15——使用Appium自动化测试爬取微信朋友圈数据_appium监测微信图片-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏27次。 一、解析过程本人使用锤子手机做测试,型号是YQ601,首先打开开发者模式确保手机能与mac相连,打开Appium客户端,配置参数如图可以理解为Appuim继承自web端的selenium,同样可以执行一些自动化操作。Appium自带了一个XPATH选择器,给用户提供了选择结果,如图这个选择器给出的结果太繁琐,所以可以改成通过查找ID的方式来构造爬虫程序。但是这里要注意,估计微信提升了自己..._appium监测微信图片

随便推点

交叉编译工具 aarch64-linux-gnu-gcc 的介绍与安装-程序员宅基地

文章浏览阅读8w次,点赞20次,收藏160次。aarch64-linux-gnu-gcc 是由 Linaro 公司基于 GCC 推出的的 ARM 交叉编译工具_aarch64-linux-gnu-gcc

数码管扫描显示verilog_如何开始Xilinx FPGA开发之旅 第二课 EGO1数码管与键盘-程序员宅基地

文章浏览阅读1.4k次。庚子年,我们的EGO1在疫情当中作为口袋实验平台成为了众多高校的复课利器。其中的成功案例更是得到了新华社网媒与CCTV教育频道的报道。借此东风,为了让更多的老师与学生熟悉了解Xilinx,更好的入门学习FPGA知识,我们的师资培训直播已开设EGO1专题直播,欢迎新老朋友跟踪关注。第二课---- EGO1数码管与键盘本周的直播我们将介绍EGO1的外设使用案例,介绍数码管扫描的原理和PS/2..._fpgaego1 键盘

python re库安装_python 库安装方法及常用库-程序员宅基地

文章浏览阅读3.6k次。python库安装方法:方法一:setpu.py1.下载库压缩包,解压,记录下路径:*:/**/……/2.运行cmd,切换到*:/**/……/目录下3.运行setup.py build4.然后输入python,进入python模块,验证是否安装成功方法二:1.Win + R 打开运行窗口,输入cmd回车2.找到pip安装路径——x:\Python xx\Scripts3. 在命令行中切换至该目录c..._rep库怎么安装

android listview fling,ListView优化: Fling(松开滑动) 过程中不加载数据-程序员宅基地

文章浏览阅读189次。1.Adapter增加滑动结束以后刷新方法//定义当前listview是否在滑动状态private boolean isScrolling = false;public void setScrolling(boolean scrolling) {this.isScrolling = scrolling;}public void refreshOnScrollEnd(AdapterView list..._android listview fling

微信公众号JSAPI自费支付总结_微信自动续费api-程序员宅基地

文章浏览阅读535次。文章目录前言一、准备操作1.公众号ID2.商户号3.商户号密钥4.域名、服务器二、步入正题1. 支付流程2. 初始化订单数据2.读入数据总结前言本编章主要是通过运行一个自费测试demo使其能够快速了解微信自费支付的实现流程,也是个人实现微信自费demo之后的记录、总结官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1一、准备操作进行微信自费支付之前请先获得以下几项必要条件,公众号和商户号需要绑定名称_微信自动续费api

java byte 字节负数-程序员宅基地

文章浏览阅读2w次。由于通讯协议中长度使用byte字节来表示,但在java中长度超过127的时候会变成负数,所以需要保证得到的长度是正数byte b & 0xFFhttp://www.blogjava.net/orangelizq/archive/2008/07/20/216228.html在剖析该问题前请看如下代码public static String bytes2HexString(

推荐文章

热门文章

相关标签