Mybatis基础知识

0.1mvc

M是指业务模型model,V是指用户界面view,C则是控制器controller,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式(pc+手机+ipad)
model:(实体类+dao+业务)   对数据和功能封装的实体类+业务类+dao类
view:(HTML+CSS+JS+jsp)  页面相关的技术(获取客户的数据+结果数据的展示)
controller:(servlet)    选择页面跳转
mvc是一种通用的软件设计模式
  • 优点
1 降低耦合度:视图层和业务层分离
2 提高代码的复用性:
3 便于分工开发
4 维护性高
  • 缺点
1 调试困难(单元测试困难)
2 增加了程序的复杂度
3 不适合中小型项目

0.2 web三层架构

对javaweb项目结构的按业务应用进行划分:
表示层:ui:user interface
      用于显示数据和接收用户输入的数据(jsp+servlet)
业务逻辑层:BLL:Business Logic Layer
      负责关键业务的处理和数据的传递(service)
持久层:DAL:data access layer
      主要负责对数据库的直接访问(dao+entity)

1 概念

mybatis:又名ibatis
         支持定制化 SQL、存储过程以及高级映射的 由Apache组织维护的开源的持久层框架  
         简单认知:替代jdbc

jdbc的四宗罪

* jdbc缺点:
*   1  频繁的创建和销毁连接:数据库服务器压力大
*   2  java代码和sql代码混合在一起:学习成本高 可读性差  维护麻烦
*   3  给占位符赋值时:麻烦易错
*   4  处理结果集时:麻烦易错

mybatis解决jdbc的缺点

1 mybatis自带连接池 对连接的创建、初始化、分配、维护、销毁进行管理
2 mybatis是面向配置的编程:把sql语句从java代码中分离::sql映射文件
3 mybatis可以实现java对象与表记录的自动映射:java对象的属性可以自动sql语句中的对应占位符赋值
4 mybatis可以实现表记录与java对象的自动映射:可以实现数据行数据自动解析为java对象

mybatis的特点

* 1 轻量级:
* 2 支持动态sql:通过标签实现sql的拼接
* 3 面向配置的编程:核心配置文件(mybatis的基本设置)+sql映射文件(同一个表的所有sql标签)
* 4 sql语句与java代码的完全分离:单独的文件:sql映射文件存储所有的sql语句
* 5 良好支持复杂的数据映射:支持原生态的sql 比较适用于功能多变 模块不确定的项目
* 6 简单易学 容易上手

orm

orm:object relational mapping 对象关系映射
    java中对象的属性与sql表中列的对应关系:
    解决的问题:给占位符赋值和解析结果集

mybatis和hibernate的区别

都是持久层框架:替代jdbc 核心都是ORM
1 mybatis简单易学  学习成本低
  hibernate比较复杂 学习成本高
2 hibernate是完全的orm框架:不存在sql  对jdbc进行了完全的封装
  mybatis不是完全的orm框架  需要手写sql
3 hibernate比较适用于传统的 表结构固定的项目
  mybatis比较适用于功能模块多变 表结构复杂的项目

2 mybatis案例1

2.1 创建项目:java项目即可

2.2 导入jar包:

commons-logging-1.1.1.jar
log4j-1.2.17.jar
mybatis-3.2.8.jar
mysql-connector-java-5.1.15-bin.jar

2.3 创建数据库

use db_11;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `sname` varchar(11) DEFAULT NULL,
  `sex` char(1) DEFAULT NULL,
  `score` float(4,1) DEFAULT NULL,
  `stid` int(11) DEFAULT NULL,
  `sage` int(11) DEFAULT NULL,
  `sdy` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_11_s_t` (`stid`),
  CONSTRAINT `fk_11_s_t` FOREIGN KEY (`stid`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=997 DEFAULT CHARSET=utf8

2.4 根据表创建实体类

public class Student   implements Serializable{
	private Integer sid;
	private String sname;
	private String sex;
	private Float score;
	private Integer stid;
	private Integer sage;
	private Boolean sdy;
    ....
}

2.5 创建mybatis的核心配置文件

  • mybatis_conf.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>
  <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>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>
  • dtd/xsd
document type defined :文档类型定义
   给xml文件制定规范:制定xml的根标签+子标签+标签的属性  

2.6 创建实体类对应的sql映射文件

  • StudentMapper.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 namespace="/">
  <!-- 每一种sql语句对应一种标签 -->
  <!-- 标签的id属性必须唯一 -->
  <!-- mybatis的sql配置文件中:#{xxx}是占位符 -->
  <!-- select标签的属性:
       resultType:结果集中"每行"对应的java对象的类型
       parameterType:参数的类型
   -->
   <!-- 当parameterType是单值类型时:#{xxx}占位符中的名字 可以随意 -->
   <!-- 当parameterType是对象类型时:#{xxx}占位符中的名字必须和对象的属性名一致 -->
  <select id="getOne" resultType="com.zhiyou100.demo01.Student" parameterType="int">
      select * from student where sid = #{id}
  </select>
   <select id="getAll" resultType="com.zhiyou100.demo01.Student">
      select * from student
  </select>
  <delete id="deleteOne" parameterType="int">
      delete from student where sid=#{sid}
  </delete>
  <update id="updateOne" parameterType="com.zhiyou100.demo01.Student">
      update student set sname=#{sname},sex=#{sex},sage=#{sage},sdy=#{sdy},score=#{score},stid=#{stid} where sid=#{sid}
  </update>
  <insert id="addOne" parameterType="com.zhiyou100.demo01.Student">
      insert into student(sname,sex,sage,score,stid,sdy) values(#{sname},#{sex},#{sage},#{score},#{stid},#{sdy})
  </insert>
</mapper>

2.7 把sql元素文件在mybatis的核心配置文件中关联

  • mybatis_conf.xml
  <!--引入所有的sql映射文件-->
  <mappers>
     <mapper resource="src/com/zhiyou100/demo01/StudentMapper.xml"/>
  </mappers>

2.8 测试

//1 获取sqlsessionfactorybuilder对象
SqlSessionFactoryBuilder  builder=new SqlSessionFactoryBuilder();
//2 sqlsessionfactorybuilder读取核心配置文件 获取sqlsessionfactory对象
File file=new File("src/com/zhiyou100/demo01/mybatis_conf.xml");
SqlSessionFactory factory=builder.build(new FileInputStream(file));
//3 获取sqlsession:类似于connection连接
SqlSession session=factory.openSession(true);//boolean参数表示是否支持事务自动提交

//只有dml才有事务:多个dml组成一个整体 同生共死
//4 通过sqlsession的方法调用sql标签 访问数据库
//获取一个
Student s1=session.selectOne("getOne",51);
System.out.println(s1);
List<Student> list=session.selectList("getAll");
for (Student s : list) {
    System.out.println("s="+s);
}
//删除一个
int hang=session.delete("deleteOne", 108);
System.out.println("删除"+hang+"个成功!");
//修改一个
hang=session.update("updateOne", new Student(51, "新xxx", "仙", 111f, 2, 12, true));
System.out.println("修改"+hang+"个成功!");
//添加一个
hang=session.insert("addOne", new Student(null, "xxx", "x", 222f, 2, 22, true));
System.out.println("添加"+hang+"个成功!");

s1=session.selectOne("getOne",51);
System.out.println(s1);
//session.commit();//事务提交
//关闭session
session.close();

3 核心配置文件的改进

3.1 显示sql语句

  • 导入jar包:commons-logging-1.1.1.jar+log4j-1.2.17.jar
  • 创建一个log4j的核心配置文件:名字必须是log4j.properties 位置必须是src
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.Java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • 核心配置文件中添加配置信息
<settings>
       <!-- 制定log4j作为日志系统:显示sql语句 -->
       <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
  • 测试
log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 214074868.
==>  Preparing: select * from student where sid = ? 
==> Parameters: 51(Integer)
<==    Columns: sid, sname, sex, score, stid, sage, sdy
<==        Row: 51, 新xxx, 仙, 111.0, 2, 12, 1
<==      Total: 1
Student [sid=51, sname=新xxx, sex=仙, score=111.0, stid=2, sage=12, sdy=true]
==>  Preparing: delete from student where sid=? 
==> Parameters: 108(Integer)
<==    Updates: 0
删除0个成功!
==>  Preparing: update student set sname=?,sex=?,sage=?,sdy=?,score=?,stid=? where sid=? 
==> Parameters: 新xxx(String), 仙(String), 12(Integer), true(Boolean), 111.0(Float), 2(Integer), 51(Integer)
<==    Updates: 1
修改1个成功!
==>  Preparing: insert into student(sname,sex,sage,score,stid,sdy) values(?,?,?,?,?,?) 
==> Parameters: xxx(String), x(String), 22(Integer), 222.0(Float), 2(Integer), true(Boolean)
<==    Updates: 1
添加1个成功!
==>  Preparing: select * from student where sid = ? 
==> Parameters: 51(Integer)
<==    Columns: sid, sname, sex, score, stid, sage, sdy
<==        Row: 51, 新xxx, 仙, 111.0, 2, 12, 1
<==      Total: 1
Student [sid=51, sname=新xxx, sex=仙, score=111.0, stid=2, sage=12, sdy=true]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@cc285f4]
Returned connection 214074868 to pool.

3.2 给实体类起个别名

方式1:每个实体类起个不同的别名

  • 在核心配置文件中添加
<!-- 给实体类起别名 -->
<typeAliases>
    <typeAlias type="com.zhiyou100.demo01.Student" alias="stu"/>
</typeAliases>
  • 在sql映射文件中 可以有别名来替代类的全称
 <select id="getOne" resultType="com.zhiyou100.demo01.Student" parameterType="int">
      select * from student where sid = #{id}
  </select>
   <select id="getAll" resultType="stu">
      select * from student
  </select>
  <delete id="deleteOne" parameterType="int">
      delete from student where sid=#{sid}
  </delete>
  <update id="updateOne" parameterType="stu">
      update student set sname=#{sname},sex=#{sex},sage=#{sage},sdy=#{sdy},score=#{score},stid=#{stid} where sid=#{sid}
  </update>
  <insert id="addOne" parameterType="com.zhiyou100.demo01.Student">
      insert into student(sname,sex,sage,score,stid,sdy) values(#{sname},#{sex},#{sage},#{score},#{stid},#{sdy})
  </insert>

方式2:指定实体类包名即可

  • 在核心配置文件中添加
  <!-- 给实体类起别名 -->
   <typeAliases>
       <package name="com.zhiyou100.demo01"/>
   </typeAliases>
  • 在sql映射文件中直接用类名即可
 <select id="getOne" resultType="Student" parameterType="int">
      select * from student where sid = #{id}
  </select>
   <select id="getAll" resultType="Student">
      select * from student
  </select>
  <delete id="deleteOne" parameterType="int">
      delete from student where sid=#{sid}
  </delete>
  <update id="updateOne" parameterType="Student">
      update student set sname=#{sname},sex=#{sex},sage=#{sage},sdy=#{sdy},score=#{score},stid=#{stid} where sid=#{sid}
  </update>
  <insert id="addOne" parameterType="com.zhiyou100.demo01.Student">
      insert into student(sname,sex,sage,score,stid,sdy) values(#{sname},#{sex},#{sage},#{score},#{stid},#{sdy})
  </insert>

3.3 对数据库四大参数单独配置

  • 创建属性集文件装四大参数:db.properties
jdbc.driverName=com.mysql.jdbc.Driver
jdbc.name=root
jdbc.pwd=root
jdbc.url=jdbc:mysql://localhost:3306/db_11
  • 在核心配置文件中引入此属性集文件
<!-- 引入四大参数的属性集文件 -->
<properties  resource="com/zhiyou100/demo01/db.properties"/>
  • 使用数据时 通过${}来获取
<environments default="e1">
    <environment id="e1">
        <!-- 制定事务管理方式 -->
        <transactionManager type="JDBC"/>
        <!-- 制定使用内置连接池:并制定连接数据库的四大参数 -->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.name}"/>
            <property name="password" value="${jdbc.pwd}"/>
        </dataSource>
    </environment>
</environments>

4 内容补充

4.1 属性集文件

后缀名是.properties
格式:属性名=属性值
作用:作为配置文件:数据之间没有关系  只有单一的名字+值这样类型的数据
  • 解析属性集文件
//创建properties对象
Properties pros=new Properties();
//关联属性集文件
File file=new File("src/com/zhiyou100/demo01/db.properties");
pros.load(new FileInputStream(file));
//获取属性值
System.out.println(pros.getProperty("jdbc.driverName"));
System.out.println(pros.getProperty("jdbc.name"));
System.out.println(pros.getProperty("jdbc.url"));
System.out.println(pros.getProperty("jdbc.pwd"));
//遍历:和遍历hashmap相同:
//获取所有的键对应的set  通过键获取值
//Set<Object>  keys=pros.keySet();


//获取所有键值对对象对应的set  通过Entry的getKey和getValue获取键和值
//Set<Entry<Object, Object>> entrys=pros.entrySet();

4.2 log4j日志系统

  • 日志系统
系统日志是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件,对用户操作进行统计。。。
分类:服务器日志 用户操作日志 错误日志 数据库日志
  • log4j
log for java 为java写的一个日志系统
  • 步骤1:导入jar
log4j-1.2.17.jar
  • 在classes下创建log4j的核心配置文件

​ 位置必须是src

​ 名字必须是log4j.properties

#日志级别
#A:off 最高等级,用于关闭所有日志记录。
#B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
#C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
#D:warm 表明会出现潜在的错误情形。
#E:info 一般和在粗粒度级别上,强调应用程序的运行全程。
#F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
#G:all 最低等级,用于打开所有日志记录。
# 指定统一的日志级别为INFO
# 指定两个记录官:stdout , R
log4j.rootCategory=INFO, stdout , R
 
#记录官stdout:类型是ConsoleAppender--要把信息打印到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#记录官stdout:日志信息格式是自定义的
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#记录官stdout:日志信息格式
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
 
#记录官stdout:类型是DailyRollingFileAppender--每天生成一个新的文件
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=E:\\log4.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL
 
log4j.logger.com.canoo.webtest=WARN
 
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN
  • 创建测试类
package test;

import org.apache.log4j.Logger;

public class Test02Log4j {
    //获取logger对象
	private static Logger logger=Logger.getLogger(Test02Log4j.class);
	public static void main(String[] args) {
		//添加日志信息
		logger.fatal("fatal....开始");
		logger.error("error....开始");
		logger.warn("warn.....开始");
		logger.info("info....开始");
		logger.debug("debug....开始");
		System.out.println("1+1=?");
		logger.fatal("fatal....算术过程中");
		logger.error("error....算术过程中");
		logger.warn("warn.....算术过程中");
		logger.info("info....算术过程中");
		logger.debug("debug....算术过程中");
		System.out.println("1+1=2!");
		logger.fatal("fatal....结束");
		logger.error("error....结束");
		logger.warn("warn.....结束");
		logger.info("info....结束");
		logger.debug("debug....结束");
	}
}

5 数据库设计三大范式

  • 数据库设计时 需要遵守的基本规则

第一范式1NF:保证列的原子性

列数据的不可分割

  • 错误案例
create table student(
   sid int primary key,
   sname varchar(11),
   saddress varchar(200)
);
insert into student values(1,"韩梅梅","河南省郑州市二七区京广路街道新月家园1单元2000室");
insert into student values(2,"韩梅1","河南郑州二七区淮河路街道升龙国际2单元3001室");
-- 获取河南学生  对saddress需要进行截取
  • 正确案例
create table student(
   sid int primary key,
   sname varchar(11),
   saddress_province varchar(10),
   saddress_city varchar(10),
   saddress_street varchar(10),
   saddress_detail varchar(20)
);
insert into student values(1,"韩梅梅","河南省","郑州市","二七区京广路街道","新月家园1单元2000室");
insert into student values(2,"韩梅1","河南省","郑州市","二七区淮河路街道","升龙国际2单元3001室");

第二范式2NF:所有列必须直接依赖主键列

消除传递依赖,一个表只描述一个事物

  • 错误案例
create table student(
   sid int primary key,
   sname varchar(11),
   school_name varchar(11),
   school_address varchar(20),
   school_type  varchar(10),
   school_no    varchar(10)  
);
insert into student values(1,"韩梅梅","陇西路小学","河南省郑州市二七区","公立小学","NO10001");
insert into student values(3,"韩2","陇西路小学","河南省郑州市二七区","公立小学","NO10001");

问题:1:student包含了描述学生的信息 还 包含了描述学校的信息

​ 2:同一个学校的学生记录中 学校的信息会出现多次

  • 正确案例

把学校相关的学校定义为学校表 在学生表中引用学校表的主键即可

create table student(
   sid int primary key,
   sname varchar(11),
   schoolid varchar(11),
   constraint kf_1 foreign key (schoolid) references school(schoolid)
);
create table school(
   schoolid    varchar(11),
   school_name varchar(11),
   school_address varchar(20),
   school_type  varchar(10)
);
insert into student values(1,"韩梅梅","NO10001");
insert into student values(3,"韩2","NO10001");
insert into school values("NO10001","陇西路小学","河南省郑州市二七区","公立小学");

第三范式3NF:所有列必须完全依赖主键列

消除部分依赖:只针对于 联合主键

  • 错误案例:订单详情表
create table order_detail(
       order_id int comment  "订单编号",
       product_name varchar(11) comment "商品名字",
       product_number int comment "商品数量",
       product_price decimal comment "商品单价",
       discount  float comment "商品折扣",
       money decimal comment "总金额",
       constraint kf_2 foreign key (order_id) references order(order_id),
       primary key(order_id,product_name)
      
);
# product_price和discount 只依赖联合主键的product_name部分:
# 再定义一个商品表
  • 正确案例:把部分依赖product_name的信息写道商品表中
create table order_detail(
       order_id int comment  "订单编号",
       product_id int comment  "商品编号",
       product_number int comment "商品数量",
       money decimal comment "总金额",
       constraint kf_21 foreign key (order_id) references order(order_id),
       constraint kf_22 foreign key (product_id) references product(product_id),
       primary key(order_id,product_id)  
);
create table product(
       product_id int primary key comment "商品编号",
       product_name varchar(11) comment "商品名字",
       product_price decimal comment "商品单价",
       discount  float comment "商品折扣"
);

6:mybatis的两种方式

方式1:原始dao方式

通过sqlsession的自带的方法(selectOne/selectLsit/delete/update/insert方法),指定标签id 调用sql配置文件中的sql标签
缺点:1 需要指定标签的id(是字符串类型) 存在硬编码 编译器无法判断是否正确  
              只有运行时 通过判断是否出现运行时异常来判断是否错误
     2  调用sqlsession的方法传递参数时:id值和参数类型、参数个数 必须参照sql映射文件     
        不利于分组开发  效率低

方式2: mapper代理方式

通过sqlsession的getMapper方法获取sql映射文件对应的接口的代理对象  通过代理对象的方法来对应sql文件中对应的标签
优点:1 把运行时异常提前到编译时期:编译器会对方法和参数进行检查
     2 符合java完全面向对象的思想
  • 创建sql映射文件对应的接口:接口的方法声明必须和sql标签一致:id+resultType+paramtertype
public interface StudentMapper {
   Student getOne(int sid);
   List<Student> getAll();
   int updateOne(Student s);
   int deleteOne(int sid);
   int addOne(Student s);
}
  • 在sql映射文件中通过namespace属性来指定对应的mapper接口
<mapper namespace="com.zhiyou100.demo02.StudentMapper">
    ...
</mapper>
  • 通过sqlsession的getMapper方法获取sql映射文件对应的接口的代理对象 通过代理对象的方法来对应sql文件中对应的标签
//通过sqlsession获取StudentMapper接口的代理对象
StudentMapper studentMapper=session.getMapper(StudentMapper.class);
//通过代理对象的方法调用sql标签
studentMapper.getOne(141);
studentMapper.getAll();
studentMapper.deleteOne(51);
studentMapper.updateOne(new Student(141, "hhhh", "圣", 111f, 2, 12, true));
studentMapper.addOne(new Student(null, "和二号和", "人", 111f, 2, 12, true));
  • 静态获取
public class MybatisUtil {
  static SqlSessionFactory sqlSessionFactory = null;
  static {
      try {
          //使用Mybatis第一步 :获取sqlSessionFactory对象
          String resource = "mybatis_conf.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
  //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例.
  // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
  public static SqlSession getSqlSession(){
      return sqlSessionFactory.openSession(true);
  }
}

7:补充#{},${}的区别

(1)#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111",如果传入的值是id,则解析成的sql为order by "id"。

(2)$将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id。

(3)#方式在很大程度上能够防止sql注入。

(4)$方式无法防止sql注入。

(5)$方式一般用于传入数据库对象,例如传入表名。

(6)一般能用#的就别用$。
posted @ 2021-11-02 23:16  RenVei  阅读(57)  评论(0编辑  收藏  举报