mybatis总结_mybatis中as起别名可以拼接-程序员宅基地

技术标签: java  数据库开发  mybatis  

一,概述:

就是对jdbc数据库操作进行封装,使用户开发者只用关注sql语句。通过xml或者注解的方式,将要执行的各种sql语句配置起来,并通过Java对象和statement中的sql语句映射生成最终的sql语句,最后由mybatis框架执行sql语句,并将结果映射成Java对象返回。

二. 工作原理:

1,分层:

a,接口层:接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
b,数据处理层:SQL查找、SQL解析、SQL执行和执行结果映射处理
c,基础支撑层:功能支撑,包括连接管理、事务管理、配置加载和缓存处理

2,实现过程:

1.读取配置文件
连数据库的相关信息
2.有了这些信息就能创建SqlSessionFactory
SqlSessionFactory的生命周期是程序级,程序运行的时候建立起来,程序结束的时候消亡
3.SqlSessionFactory建立SqlSession,目的执行sql语句
SqlSession是过程级,一个方法中建立,方法结束应该关闭
4.调用MyBatis的statementHandler提供的Api执行Sql语句
5.SQL语句放在Map配置文件里面
6.执行SQl语句,不同的SQl语句返回不同的结果
1、 mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。
2、 mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
3、 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
4、 SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
5、 Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型

Configuration.xml:该配置文件是MyBatis的全局配置文件,在这个文件中可以配置诸多项目,但是一般项目中,并不会配置太多内容,常用的内容是别名设置,拦截器设置等,至于环境设置与Mapper映射文件的注册会转移到Spring配置文件中(SSM整合之后),而其余大部分的配置项都采用默认的配置。
  XMLConfigBuilder:该类是XML配置构建者类,是用来通过XML配置文件来构建Configuration对象实例,构建的过程就是解析Configuration.xml配置文件的过程,期间会将从配置文件中获取到的指定标签的值逐个添加到之前创建好的默认Configuration对象实例中。
  Configuration:该类是MyBatis的配置类,创建这个类的目的就是为了使用其对象作为项目全局配置对象,这样通过配置文件配置的信息可以保存在这个配置对象中,而这个配置对象在创建好之后是保存在JVM的Heap内存中的,方便随时读取。不然每次需要配置信息的时候都要临时从磁盘配置文件中获取,代码复用性差的同时,也不利于开发。
  SqlSessionFactoryBuilder:该类是SqlSessionFactory(会话工厂)的构建者类,之前描述的操作其实全是从这里面开启的,首先就是调用XMLConfigBuilder类的构造器来创建一个XML配置构建器对象,利用这个构建器对象来调用其解析方法parse()来完成Configuration对象的创建,之后以这个配置对象为参数调用会话工厂构建者类中的build(Configuration config)方法来完成会话工厂对象的构建。
  SqlsessionFactory:该接口是会话工厂,是用来生产会话的工厂接口,DefaultSqlSessionFactory是其实现类,是真正生产会话的工厂类,这个类的实例的生命周期是全局的,它只会在首次调用时生成一个实例(单例模式),就一直存在直到服务器关闭。
  openSession():在最后的build(Configuration config)方法中会返回一个DefaultSqlSessionFactory类的实例,这个类是MyBatis提供的默认会话工厂类,而我们使用的也正是这个类中的来openSession()方法来完成SqlSession对象的创建。
  SqlSession:该接口是会话,是项目与数据库之间的会话,类似于客户端与服务器之间的会话(session),这个SqlSession的生命周期是方法级的,因为他是非线程安全的,针对每一次数据库访问都要创建一个SqlSession,获取到返回结果之后,这个SqlSession就会被废弃。这区别于SqlSessionFactory的生命周期。
  Executor:执行器接口,SqlSession会话是面向程序员的,而内部真正执行数据库操作的却是Executor执行器,可以将Executor看作是面向MyBatis执行环境的,SqlSession就是门面货,Executor才是实干家。通过SqlSession产生的数据库操作,全部是通过调用Executor执行器来完成的。
  StatementHandler:该类是Statement处理器,封装了Statement的各种数据库操作方法execute(),可见MyBatis其实就是将操作数据库的JDBC操作封装起来的一个框架,同时还实现了ORM罢了。
  ResultSetHandler:结果集处理器,如果是查询操作,必定会有返回结果,针对返回结果的操作,就要使用ResultSetHandler来进行处理,这个是由StatementHandler来进行调用的。这个处理器的作用就是对返回结果进行处理。

三,三种模式

一对一:一个成绩 一个学生

<association 表示一对多,将查询结果中 一行中的数据 设置到 对应score 对应中属性 student

【总结】:

  • association:为多表一对一的的应映射关系
  • javaType:为所用属性的java类型
<resultMap id="scoreMap1" type="score">
        <id property="scoreid" column="scoreid"></id>
        <result property="coursename" column="coursename"></result>
        <result property="score" column="score"></result>
        <result property="studentid" column="studentid"></result>

        <association property="student" javaType="student">
            <id property="id" column="studentid"></id>
            <result property="name" column="name"></result>
            <result property="age" column="age"></result>
            <result property="sex" column="sex"></result>
            <result property="height" column="height"></result>
        </association>
</resultMap>

    <select id="findAllScoreWithStudent" resultMap="scoreMap1">
            SELECT a.scoreid,a.coursename,a.score,a.studentid,b.id,b.name,b.age,b.sex,b.height FROM score_tb a LEFT JOIN student_tb b ON a.studentid = b.id
    </select>

一对多:一个学生有多个成绩

 <resultMap id="studentWithSocreMap" type="student" >

        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="height" column="height"></result>

        <collection property="scoreList" ofType="score">
            <id property="scoreid" column="scoreid"></id>
            <result property="coursename" column="coursename"></result>
            <result property="score" column="score"></result>
            <result property="studentid" column="id"></result>
        </collection>

    </resultMap>


    <select id="findAllStudentWithScore" resultMap="studentWithSocreMap" >
        SELECT a.id,a.name,a.age,a.sex,a.height,b.scoreid,b.coursename,b.score,b.studentid  FROM student_tb a LEFT JOIN score_tb b ON a.id = b.studentid
    </select>

多对多:多对多其实不存在,实际就是 两个/多个 一对多

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JbYYfQv4-1627901784025)(C:\Users\22564\AppData\Roaming\Typora\typora-user-images\image-20210611125126948.png)]

select * from role_tb r LEFT JOIN student_role_tb sr on r.id = sr.roleid
  LEFT JOIN student_tb s on sr.studentid = s.id
<resultMap id="roleMap1" type="role">
        <id property="id" column="id"></id>
        <result property="rolename" column="rolename"></result>

        <collection property="studentList" ofType="Student">
            <id property="id" column="studentid"></id>
            <result property="name" column="name"></result>
            <result property="age" column="age"></result>
            <result property="sex" column="sex"></result>
            <result property="height" column="height"></result>
        </collection>
</resultMap>

    <select id="findAllRoleWithStudent" resultMap="roleMap1">
        select r.id id,r.rolename rolename,s.name name,s.age age,s.sex sex,s.height height,sr.studentid studentid
            from role_tb r LEFT JOIN student_role_tb sr on r.id = sr.roleid
                LEFT JOIN student_tb s on sr.studentid = s.id
    </select>

(1)事务模块,抽象工厂模式
(2)数据源:数据源接口中定义了两个获取数据库连接Connection的方法,可见数据源的目的所在,不论其使用什么原理实现,其目的就是为了对外提供数据库连接的获取接口。unpooled:非池型数据源。pooled:同步的线程安全的池型数据源。jndi:托管型

四,问题:

1,#{}和${}的区别是什么?

{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理时,就是把时,就是把{}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。

2,当实体类中的属性名和表中的字段名不一样 ,怎么办

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
第2种: 通过来映射字段名和实体类属性名的一一对应的关系

3,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个标签,都会被解析为一个MappedStatement对象。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

4,Mybatis是如何进行分页的

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

5,在mapper中如何传递多个参数

对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可,

在mybatis 中 如果有多个参数 并且使用 #{参数名} 必须在方法中为参数声明 别名 @Param(“sex”)

也可以使用 arg0 arg1 或者 param1 param2
* 如果是传多个属性(参数)
* 也可以直接传对象
* findStudentBySexAndAge(Student student);
* 或者直接传对象
* findStudentBySexAndAge(Map map);

 findStudentBySexAndAge(@Param("sex") String sex,@Param("age") int age);
6,缓存问题:

缓存:比如执行select * from student 第一次,sqlsesion 没有缓存去数据库找,缓存起来,第二次执行select * from student 直接去缓存找。Mybatis在查询时会采用缓存机制,分为一级缓存和二级缓存,

好处:1.查询效率高(快)2.降低mysql服务器请求查询压力

mybatis 一级二级缓存

一级缓存就是基于sqlsesion 的缓存

二级缓存基于namespace的缓存,二级缓存是 多个 sqlsesion 共享的

一级缓存默认就会开启,二级缓存需要配置才可以使用。无论是一级缓存,还是二级缓存共同的特点:所有的查询都会缓存,但是只要发生增删改,缓存立即清空否则会有脏数据问题。
一级缓存:一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。一旦发生增删改,缓存立即失效。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache、Hazelcast等。
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
在缓存的作用域中,如果调用的方法的参数一样,就会使用缓存中查询的结果,而不会再次查询数据库。

二级缓存:基于namespace,有多个Sqlsession共享

二级缓存开启:

1、开启缓存开关

<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>

        <!-- 开启全局懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

        <!--开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>

</settings>

2、对应的dao.xml开启缓存

<!--
         <cache>  开启二级缓存
            eviction="LRU" 缓存是有大小限制,超过大小要 清除一些缓存
                    - LRU - 最近最少回收,移除最长时间不被使用的对象
                    - FIFO - 先进先出,按照缓存进入的顺序来移除它们
                    - SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
                    - WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
            size="1024"  缓存 最多 1024 条数 sql 对应的数据
            flushInterval="60000"  60s 缓存 刷新一次
            readOnly="true" 是否只读  不能获取缓存中对象的引用,不能直接修改缓存对象
                     "false" 能获取缓存中对象的引用,能直接修改缓存对象
                      
            blocking="true" 在读取缓存时是否阻塞 
    -->
<cache eviction="LRU" size="1024" flushInterval="60000" readOnly="true" blocking="true">
</cache>

3、使用缓存

<!--
        在查选标签中配置 useCache="true" 使用缓存
        默认值就是true 使用缓存    
-->
<select id="findStudentById" resultType="Student" useCache="true">
        select  * from student_tb where id = #{id}
</select>

【注意】:一级缓存和二级缓存同时存在,可能会引入脏数据

【解决方案】:

1、第一种不使用一级缓存

<!-- 将一级缓存修改为STATEMENT表示不使用一级缓存
                  SESSION表示使用一级缓存
-->
<setting name="localCacheScope" value="STATEMENT"/>

2、在spring中使用mybatis,每次调用mapper对应的方法,都使用新的Sqlsession

7、Mybatis基于注解的开发
public interface StudentDao{
    

    @Select("select * from student_tb where id = #{id}")
    Student findStudentById(int id);

    @Insert("insert into student_tb (name,age,sex,height) values(#{name},#{age},#{sex},#{height})")

    @SelectKey(resultType = Integer.class,keyProperty = "id",keyColumn = "id",before = false,statement = "select last_insert_id()")
	//获取自增id  statement = "" 获取自增id 的sql
    int addStudent(Student student);

    @Update("update student_tb set name = #{name},age = #{age},sex=#{sex},height=#{height} where id = #{id}")
    int updateStudent(Student student);

    @Delete("delete from student_tb where id = #{id}")
    int deleteStudent(int id);

}

自定义resultMap完成数据库列名和实体类名不一致的问题

@Results

@Select("select * from student_tb")
@Results(id = "studentResult1",value = {
        @Result(id = true,property = "id",column = "id"),
        @Result(property = "name",column = "name"),
        @Result(property = "age",column = "age"),
        @Result(property = "sex",column = "sex"),
        @Result(property = "height",column = "height")
    })// 相当于xml 中 <resultMap> 声明map
    // @Result(id = true,property = "id",column = "id") 相当于 <id property="id" column="id"></id>
    List<Student> findAllStudent();

    @Select("select * from student_tb where sex = #{sex}")
    @ResultMap(value = "studentResult1")// 使用@ResultMap 引用已经在其他方法上声明的 		@Results
    List<Student> findAllStudentBySex(String sex);

基于注解的懒加载

@Select("select * from student_tb")
@Results(id = "studentResult2",value = {
			@Result(id = true,property = "id",column = "id"),
            @Result(property = "name",column = "name"),
            @Result(property = "age",column = "age"),
            @Result(property = "sex",column = "sex"),
            @Result(property = "height",column = "height"),
            @Result(property = "scoreList",column = "id",many = @Many(select = "com.qfedu.dao.ScoreDao.findAllScoreByStudentId",fetchType = FetchType.LAZY))
    })
    List<Student> findAllStudentWithScorelazy();
9,延迟加载:

延迟加载就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗。

1、开启懒加载:

<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>

        <!-- 开启全局懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

    </settings>

2、一对多懒加载:

 <!--

        一对多懒加载
            column="id" 两张表关联的id

            select="com.qfedu.dao.ScoreDao.findAllScoreByStudentId"  调用 更具学生id 查询所有成绩方法

             fetchType="lazy" 懒加载
             fetchType="eager" 立即加载
    -->
    <resultMap id="studentMap1" type="Student">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="height" column="height"></result>

        <collection property="scoreList" ofType="Score" column="id" select="com.qfedu.dao.ScoreDao.findAllScoreByStudentId"
                    fetchType="lazy">
        </collection>
    </resultMap>

    <select id="findStudentByLazy" resultMap="studentMap1">
        select  * from  student_tb
    </select>
10、PageHelper分页

pagehelper 是mybatis 的一个插件,帮助我们完成分页查询

1、引入依赖

<!--配置分页-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.4</version>
</dependency>

2、在配置文件中引入

<!--
   配置pagehelper 插件注意  必须在 <environments 之前
-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 使用MySQL方言的分页 -->
            <property name="helperDialect" value="mysql"/><!--如果使用mysql,这里value为mysql-->
            <!--  
                如果 pegesize为0 查询所有
            -->
            <property name="pageSizeZero" value="true"/>
        </plugin>
    </plugins>

3、使用

 @Test
    public void pageHelperTest(){

        // PageHelper 帮助 下面的 sql 完成分页
        // 在 select * from student_tb  拼接 limit index,pagesize
//        select * from student_tb limit ?,?
        PageHelper.startPage(1, 3);// 在查选语句之前 调用

        List<Student> allStudentList = studentDao2.findAllStudent();

        // 获取分页信息
        PageInfo<Student> pageInfo = new PageInfo<Student>(allStudentList);

        System.out.println("总数量"+pageInfo.getTotal());
        System.out.println("当前页"+pageInfo.getPageNum());
        System.out.println("每页多少"+pageInfo.getPageSize());
        System.out.println("总页数"+pageInfo.getPages());

        for (Student student : allStudentList) {
            System.out.println("student:"+student);
        }

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

智能推荐

51单片机的中断系统_51单片机中断篇-程序员宅基地

文章浏览阅读3.3k次,点赞7次,收藏39次。CPU 执行现行程序的过程中,出现某些急需处理的异常情况或特殊请求,CPU暂时中止现行程序,而转去对异常情况或特殊请求进行处理,处理完毕后再返回现行程序断点处,继续执行原程序。void 函数名(void) interrupt n using m {中断函数内容 //尽量精简 }编译器会把该函数转化为中断函数,表示中断源编号为n,中断源对应一个中断入口地址,而中断入口地址的内容为跳转指令,转入本函数。using m用于指定本函数内部使用的工作寄存器组,m取值为0~3。该修饰符可省略,由编译器自动分配。_51单片机中断篇

oracle项目经验求职,网络工程师简历中的项目经验怎么写-程序员宅基地

文章浏览阅读396次。项目经验(案例一)项目时间:2009-10 - 2009-12项目名称:中驰别克信息化管理整改完善项目描述:项目介绍一,建立中驰别克硬件档案(PC,服务器,网络设备,办公设备等)二,建立中驰别克软件档案(每台PC安装的软件,财务,HR,OA,专用系统等)三,能过建立的档案对中驰别克信息化办公环境优化(合理使用ADSL宽带资源,对域进行调整,对文件服务器进行优化,对共享打印机进行调整)四,优化完成后..._网络工程师项目经历

LVS四层负载均衡集群-程序员宅基地

文章浏览阅读1k次,点赞31次,收藏30次。LVS:Linux Virtual Server,负载调度器,内核集成, 阿里的四层SLB(Server Load Balance)是基于LVS+keepalived实现。NATTUNDR优点端口转换WAN性能最好缺点性能瓶颈服务器支持隧道模式不支持跨网段真实服务器要求anyTunneling支持网络private(私网)LAN/WAN(私网/公网)LAN(私网)真实服务器数量High (100)High (100)真实服务器网关lvs内网地址。

「技术综述」一文道尽传统图像降噪方法_噪声很大的图片可以降噪吗-程序员宅基地

文章浏览阅读899次。https://www.toutiao.com/a6713171323893318151/作者 | 黄小邪/言有三编辑 | 黄小邪/言有三图像预处理算法的好坏直接关系到后续图像处理的效果,如图像分割、目标识别、边缘提取等,为了获取高质量的数字图像,很多时候都需要对图像进行降噪处理,尽可能的保持原始信息完整性(即主要特征)的同时,又能够去除信号中无用的信息。并且,降噪还引出了一..._噪声很大的图片可以降噪吗

Effective Java 【对于所有对象都通用的方法】第13条 谨慎地覆盖clone_为继承设计类有两种选择,但无论选择其中的-程序员宅基地

文章浏览阅读152次。目录谨慎地覆盖cloneCloneable接口并没有包含任何方法,那么它到底有什么作用呢?Object类中的clone()方法如何重写好一个clone()方法1.对于数组类型我可以采用clone()方法的递归2.如果对象是非数组,建议提供拷贝构造器(copy constructor)或者拷贝工厂(copy factory)3.如果为线程安全的类重写clone()方法4.如果为需要被继承的类重写clone()方法总结谨慎地覆盖cloneCloneable接口地目的是作为对象的一个mixin接口(详见第20_为继承设计类有两种选择,但无论选择其中的

毕业设计 基于协同过滤的电影推荐系统-程序员宅基地

文章浏览阅读958次,点赞21次,收藏24次。今天学长向大家分享一个毕业设计项目基于协同过滤的电影推荐系统项目运行效果:项目获取:https://gitee.com/assistant-a/project-sharing21世纪是信息化时代,随着信息技术和网络技术的发展,信息化已经渗透到人们日常生活的各个方面,人们可以随时随地浏览到海量信息,但是这些大量信息千差万别,需要费事费力的筛选、甄别自己喜欢或者感兴趣的数据。对网络电影服务来说,需要用到优秀的协同过滤推荐功能去辅助整个系统。系统基于Python技术,使用UML建模,采用Django框架组合进行设

随便推点

你想要的10G SFP+光模块大全都在这里-程序员宅基地

文章浏览阅读614次。10G SFP+光模块被广泛应用于10G以太网中,在下一代移动网络、固定接入网、城域网、以及数据中心等领域非常常见。下面易天光通信(ETU-LINK)就为大家一一盘点下10G SFP+光模块都有哪些吧。一、10G SFP+双纤光模块10G SFP+双纤光模块是一种常规的光模块,有两个LC光纤接口,传输距离最远可达100公里,常用的10G SFP+双纤光模块有10G SFP+ SR、10G SFP+ LR,其中10G SFP+ SR的传输距离为300米,10G SFP+ LR的传输距离为10公里。_10g sfp+

计算机毕业设计Node.js+Vue基于Web美食网站设计(程序+源码+LW+部署)_基于vue美食网站源码-程序员宅基地

文章浏览阅读239次。该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流项目运行环境配置:项目技术:Express框架 + Node.js+ Vue 等等组成,B/S模式 +Vscode管理+前后端分离等等。环境需要1.运行环境:最好是Nodejs最新版,我们在这个版本上开发的。其他版本理论上也可以。2.开发环境:Vscode或HbuilderX都可以。推荐HbuilderX;3.mysql环境:建议是用5.7版本均可4.硬件环境:windows 7/8/10 1G内存以上;_基于vue美食网站源码

oldwain随便写@hexun-程序员宅基地

文章浏览阅读62次。oldwain随便写@hexun链接:http://oldwain.blog.hexun.com/ ...

渗透测试-SQL注入-SQLMap工具_sqlmap拖库-程序员宅基地

文章浏览阅读843次,点赞16次,收藏22次。用这个工具扫描其它网站时,要注意法律问题,同时也比较慢,所以我们以之前写的登录页面为例子扫描。_sqlmap拖库

origin三图合一_神教程:Origin也能玩转图片拼接组合排版-程序员宅基地

文章浏览阅读1.5w次,点赞5次,收藏38次。Origin也能玩转图片的拼接组合排版谭编(华南师范大学学报编辑部,广州 510631)通常,我们利用Origin软件能非常快捷地绘制出一张单独的绘图。但是,我们在论文的撰写过程中,经常需要将多种科学实验图片(电镜图、示意图、曲线图等)组合在一张图片中。大多数人都是采用PPT、Adobe Illustrator、CorelDraw等软件对多种不同类型的图进行拼接的。那么,利用Origin软件能否实..._origin怎么把三个图做到一张图上

51单片机智能电风扇控制系统proteus仿真设计( 仿真+程序+原理图+报告+讲解视频)_电风扇模拟控制系统设计-程序员宅基地

文章浏览阅读4.2k次,点赞4次,收藏51次。51单片机智能电风扇控制系统仿真设计( proteus仿真+程序+原理图+报告+讲解视频)仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0042。_电风扇模拟控制系统设计