Java之JDBC,Maven,MYBatis

news/2024/11/16 23:25:14/

前言

就是用来操作数据库的

JDBC_5">1.JDBC快速入门

注意在使用前一定要导入jar包
在这里插入图片描述
在模块那里新建目录,新建lib,粘贴复制jar包,我这个jar设置的是模块有效

java">package test1017;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class test {public static void main(String[] args) throws Exception {//注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//获取连接String url="jdbc:mysql://127.0.0.1:3306/test";//最后一个为数据库名?useSSL=falseString username="root";//用户名String password="kl12151215";//密码Connection conn=DriverManager.getConnection(url,username,password);//获取sql对象Statement stmt=conn.createStatement();String sql="insert into emp3 values('bb',2)";//sql语句//执行sqlint count=stmt.executeUpdate(sql);//executeUpdate只能用于INSERT、UPDATE、DELETESystem.out.println(count);//释放资源stmt.close();conn.close();}
}

在这里插入图片描述
在这里插入图片描述
就这样我们就可以操作了

JDBCAPI_48">2.JDBC之API

2.1DriverManager

作用就是
1.注册驱动
2.获取数据库连接

java">Connection conn=DriverManager.getConnection(url,username,password);

比如这个就是获取数据库连接
在这里插入图片描述
而这个forName,其实底层调的就是DriverManager的注册驱动作用

然后就是mysql5之后的驱动包,可以不用写注册驱动了
在这里插入图片描述

java">//        Class.forName("com.mysql.cj.jdbc.Driver");

意思是把这个省略掉,也可以运行

然后就是链接的时候,如果链接的是本机的mysql服务器,而且默认端口号为3306.则就可以省略这两个不写

java">//        String url="jdbc:mysql://127.0.0.1:3306/test";//最后一个为数据库名?useSSL=falseString url="jdbc:mysql:///test";//最后一个为数据库名

然后就是可以在后面写上useSSL=false,解决一些警告提示,但是高版本的没有警告提示

java">String url="jdbc:mysql:///test?useSSL=false";//最后一个为数据库名

如果还要继续配置参数,加上&继续添加就可以了

2.2 Connection

Connection
1.就是获取执行的sql对象,已经用过了
2.就是事务管理

java">        String sql1="insert into emp3 values('bb',2)";//sql语句String sql2="insert into emp3 values('cc',1)";//sql语句try {//开始事务conn.setAutoCommit(false);//执行sqlint count1=stmt.executeUpdate(sql1);int count2=stmt.executeUpdate(sql2);System.out.println(count1);System.out.println(count2);//提交事务conn.commit();} catch (Exception e) {conn.rollback();e.printStackTrace();}
java">conn.setAutoCommit(false);

就是开启事务,设置为false的意思就是需要手动提交事务,true就是自动提交事务
commit就是我们手动写的提交事务

至于回滚事务的话,如果出错了就抛异常吧,反正也不会真正执行的,都是假的执行,只有提交了才是真正的执行,抛到异常那里,在回滚,回滚的话,就算在自己这个用户也是无法看到变化的,不回滚的话,那么自己就会看到异常前的sql语句带来的变化

2.3 Statement

Statement有两个方法

stmt.executeUpdate()执行的是DML和DDL语句,返回值是语句影响的行数,一般来说,执行失败了,就会返回0,但是DDL中删除的操作,执行成功返回的也是0

stmt.executeQuery()执行的是DQL语句,就是查询语句,返回值是ResultSet

DML语句

java">Statement stmt=conn.createStatement();String sql1="update emp3 set name ='cc' where name = 'aa' ";//sql语句//开始事务conn.setAutoCommit(false);//执行sqlint count1=stmt.executeUpdate(sql1);System.out.println(count1);

在这里插入图片描述

java">        if(count1>0){System.out.println("修改成功");}else {System.out.println("修改失败");}

再加上这个就更完美了

DDL语句

java">        String sql1="create database aaaa ";//sql语句

在这里插入图片描述
返回1就是执行成功

java">        String sql1="drop database aaaa ";//sql语句

在这里插入图片描述
而drop时,成功的返回值就是0

ResultSet就是stmt.executeQuery()的返回值
它指向的就是那个你打印出的那个表
在这里插入图片描述

它一开始指向的name那一行,然后它有方法
next()方法就是将指向的光标下移一行,然后就是返回值,如果为有效行的话,返回true,反之

xxx getXxx(参数) :这个就是获取数据
xxx:是数据类型,如:int getInt(参数) 表明你要获取的数据是int类型的
参数:可以是int,代表列的编号
或者String:代表列的名称

java">public class test {public static void main(String[] args) throws Exception {String url="jdbc:mysql:///test?useSSL=false";//最后一个为数据库名String username="root";//用户名String password="kl12151215";//密码Connection conn=DriverManager.getConnection(url,username,password);//获取sql对象Statement stmt=conn.createStatement();String sql1="select * from emp3";//sql语句//执行sqlResultSet rs=stmt.executeQuery(sql1);while(rs.next()){int id=rs.getInt(2);String name=rs.getString(1);System.out.println(id);System.out.println(name);System.out.println("----------------");}//释放资源rs.close();//这下rs也要释放资源stmt.close();conn.close();}
}

在这里插入图片描述

这样的话,我们定义一个类,就可以储存这些数据了
然后定义一个链表,就可以全部数据存储了

java">            int id=rs.getInt("dep_id");String name=rs.getString("name");

或者这样写也是一样的

2.4PreparedStatement

1.这个可以预编译sql语句,第二这个可以防止sql注入问题

sql注入问题就是你登录的时候,账号乱写,然后密码写入一些特定的sql语句,让我们登录成功

比如密码输入 'or ‘1’ = '1

sql注入演示

在这里插入图片描述

我们这里假设name就是用户,dep_id就是密码

java">        String name="bb";//用户名String dep_id="2";String sql1="select * from emp4 where name='' and dep_id= '' ";

先这样

java">        String sql1="select * from emp4 where name=' " +name+" ' and dep_id= '  "  +dep_id+"' ";

再把name插进去,这样sql语句就写好了

java">        String name="bb";//用户名String dep_id="2";String sql1="select * from emp4 where name='"+name+"'and dep_id= '"+dep_id+"'";//注意的是,就是空格不要太大,不然读不出来ResultSet rs=stmt.executeQuery(sql1);if(rs.next()){System.out.println("登录成功");}else{System.out.println("登录失败");}

在这里插入图片描述
下面我们将pid_t换成 'or ‘1’ = '1

java">        String dep_id="'or '1' = '1";

在这里插入图片描述
结果还是这样的

为什么呢

我们看看最后的sql语句就知道了

java">select * from emp4 where name='bb'and dep_id= ''or '1' = '1'

可以看出,因为’1’ = '1’始终为真,所以,这个sql语句就为真,所以就会打印出所有东西,所以就会登录正确

因为这个密码改变了sql语句的意思,所以登录成功了,所以我们引入PreparedStatement,就可以防止了

PreparedStatement演示

java">public class test {public static void main(String[] args) throws Exception {String url="jdbc:mysql:///test?useSSL=false";//最后一个为数据库名String username="root";//用户名String password="kl12151215";//密码Connection conn=DriverManager.getConnection(url,username,password);Statement stmt=conn.createStatement();String name="bb";//用户名String dep_id="'or '1' = '1";
//        String dep_id="aa";String sql1="select * from emp4 where name=? and dep_id=?";//首先密码和用户我们用?替代//PreparedStatement对象通过conn获取PreparedStatement pstmt=conn.prepareStatement(sql1);//这里要传入sql语句pstmt.setString(1,name);pstmt.setString(2,dep_id);//给?设置值ResultSet rs=pstmt.executeQuery();//这里就不需要传sql了if(rs.next()){System.out.println("登录成功");}else{System.out.println("登录失败");}rs.close();stmt.close();conn.close();}
}

在这里插入图片描述
这样我们就解决了sql注入问题

它是怎么解决的呢
它其实是把单引号转义了,让它就是一个’'里面的一个正常的数据,不会产生’‘

java">select * from emp4 where name='bb' and dep_id= '\'or \1\ = \1';#'or '1' = '1

下面讲一下预编译的问题

sql语句在执行的过程中,会经历检查sql语法,编译sql,执行sql的步骤

而预编译就是我们在执行到PreparedStatement pstmt=conn.prepareStatement(sql1);的时候,就已经检查sql语法,编译sql了,后面设置?的时候,只需要替换执行sql就可以了

这样的话,我们执行两条sql语句的话,不用PreparedStatement 的话,我们就要走两遍检查sql语法,编译sql,执行sql

用了PreparedStatement ,检查sql语法,编译sql走一遍,,执行sql走两遍就可以了

但是要开启预编译的话,要输入useServerPreStmts=true
要设置这个

java">        String url="jdbc:mysql:///test?useSSL=false&useServerPreStmts=true";

2.5 数据库连接池

数据库连接池就和线程池是一样的,允许程序重复使用一个现有的数据库链接,而不是重新在建立一个

在这里插入图片描述

这个就是配置文件

java">public class test {public static void main(String[] args) throws Exception {//导入jar包//lib文件//定义配置文件//文件//加载配置文件Properties prop=new Properties();prop.load(new FileInputStream("test1017/src/druid.properties"));//路径是相对路径//获取连接池对象DataSource dataSource= DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connection connection=dataSource.getConnection();System.out.println(connection);}
}

在这里插入图片描述
一般来说,有了数据库连接池,我们就不需要自己手动去连接本地的数据库了,它自己会链接了,因为配置文件都写好了

3.实操

java">public class Brand {String name;String dep_id;public String getName() {return name;}public String getDep_id() {return dep_id;}public void setName(String name) {this.name = name;}public void setDep_id(String dep_id) {this.dep_id = dep_id;}public Brand(String name, String dep_id) {this.name = name;this.dep_id = dep_id;}public Brand() {}
}

定义一个类来存每行
定义一个链表来存整个表

java">public class test {public static void main(String[] args) throws Exception {//导入jar包//lib文件//定义配置文件//文件//加载配置文件Properties prop=new Properties();prop.load(new FileInputStream("test1017/src/druid.properties"));//获取连接池对象DataSource dataSource= DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connection conn=dataSource.getConnection();//sqlString sql="select * from emp4";//获取pstmtPreparedStatement pstmt=conn.prepareStatement(sql);//设置?参数//执行ResultSet rs=pstmt.executeQuery();//然后存储}
}

这个是查询的操作,或者是填充的操作

添加操作

java">insert into emp4(name dep_id) values(?,?);//有id的话,不用写,因为是默认自增长的

修改数据

java">update emp4
set name=?,dep_id=?
where id=?

删除

java">delete from emp4 where id=?

4. maven

maven是一个项目管理和构建的工具
它的项目结构,构建流程,还有依赖管理都是很统一的

下面讲一下maven的构建
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
给test添加resources
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
xml里面可以导入jar包

java"><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--当前项目的坐标--><groupId>com.itheima</groupId><artifactId>test1</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!--导入mysql的jar包--><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
<!--scope的意思是说明jar的作用范围,所以这样只有test,测试环境,可以用junit,不写这个就是默认全部范围的--></dependency></dependencies></project>

比如这样

然后就可以写代码了

java里面新建软件包,然后建java类就可以了

CTRL+A是全选

MyBatis_520">5.MyBatis

5.1查询

在这里插入图片描述

java">
drop table if exists tb_brand;
create table tb_brand
(#主键id int primary key auto_increment,#品牌名称brand_name varchar(20),#企业名称company_name varchar(20),#排序字段ordered int,#描述信息description varchar(100),#状态  0:禁用  1:启用status   int
);
insert into tb_brand(brand_name,company_name,ordered,description,status)values ('三只松鼠','三只松鼠股份有限公司',5,'好吃不上火',0),('华为','华为技术有限公司',108,'华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界',1),('小米','小米科技有限公司',50,'are you ok',1);
SELECT * FROM tb_brand;
java">package com.itheima.pojo;public class Brand {private int id ;private String brand_name  ;private String company_name  ;private String ordered        ;private String description    ;private int status       ;public int getId() {return id;}public String getBrand_name() {return brand_name;}public String getCompany_name() {return company_name;}public String getOrdered() {return ordered;}public String getDescription() {return description;}public int getStatus() {return status;}public void setId(int id) {this.id = id;}public void setBrand_name(String brand_name) {this.brand_name = brand_name;}public void setCompany_name(String company_name) {this.company_name = company_name;}public void setOrdered(String ordered) {this.ordered = ordered;}public void setDescription(String description) {this.description = description;}public void setStatus(int status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brand_name='" + brand_name + '\'' +", company_name='" + company_name + '\'' +", ordered='" + ordered + '\'' +", description='" + description + '\'' +", status=" + status +'}';}
}
java">package com.itheima.mapper;import com.itheima.pojo.Brand;import java.util.List;public interface BrandMapper {
//  查询所有public List<Brand> selectAll();}
java"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间-->
<mapper namespace="com.itheima.mapper.UserMapper"></mapper>
java"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间-->
<mapper namespace="com.itheima.mapper.BrandMapper"><select id="selectAll" resultType="brand">select *from tb_brand;</select>
</mapper>
java">public class MybatisTest {//测试用例@Testpublic void testSelectAll() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession=sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper=sqlSession.getMapper(BrandMapper.class);//4.执行方法List<Brand> brands=brandMapper.selectAll();System.out.println(brands);//5.释放资源sqlSession.close();//Mybatis完成操作三步,,,编写接口方法,编写sql,执行方法,,,,,,}
}

在这里插入图片描述
如果我们Brand里面的名称为brandName
驼峰命名模式,那么就有可能查询不到
但是我们可以取别名

java">package com.itheima.pojo;public class Brand {private int id ;private String brandName  ;private String companyName  ;private String ordered        ;private String description    ;private int status       ;public int getId() {return id;}public String getbrandName() {return brandName;}public String getcompanyName() {return companyName;}public String getOrdered() {return ordered;}public String getDescription() {return description;}public int getStatus() {return status;}public void setId(int id) {this.id = id;}public void setbrandName(String brandName) {this.brandName = brandName;}public void setcompanyName(String companyName) {this.companyName = companyName;}public void setOrdered(String ordered) {this.ordered = ordered;}public void setDescription(String description) {this.description = description;}public void setStatus(int status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered='" + ordered + '\'' +", description='" + description + '\'' +", status=" + status +'}';}
}

比如这样,所有都变成了驼峰模式,但是数据库里面还是下划线的模式
所以找不到

在这里插入图片描述
我们可以用取别名的方法
在sql语句的配置文件那里

java"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间-->
<mapper namespace="com.itheima.mapper.BrandMapper">
<!--数据库表的字段名称和实体类的属性名称不一样,就不能自动封装数据,取别名就可以了--><select id="selectAll" resultType="brand">select id ,brand_name as brandName,company_name as companyName,ordered,description,statusfrom tb_brand;</select>
<!--    <select id="selectAll" resultType="brand">-->
<!--        select *-->
<!--        from tb_brand;-->
<!--    </select>-->
</mapper>

在这里插入图片描述
第一种方法是取别名,让别名和实体类的属性名一样就可以了
第二种方法就是定义sql片段

java"><sql id="brand_column">id ,brand_name as brandName,company_name as companyName,ordered,description,status</sql><select id="selectAll" resultType="brand">select<include refid="brand_column" />from tb_brand;</select>

在这里插入图片描述
缺点就是不灵活,确定了那么多个

接下来用resultMap

java">    <resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/></resultMap><select id="selectAll" resultMap="brandResultMap">select*from tb_brand;</select>

brandResultMap随便取,是一个唯一标识
brand是类型,也就是别名com.itheima.pojo.Brand的,映射的类型,支持别名
result 是一般字段的映射
id column中id是对主键的映射
companyName是一般字段
column是表的列名
property实体类的属性名
1.定义标签
2.属性替换
在这里插入图片描述

5.2 查看详情

根据id查询详情
在这里插入图片描述

java">public interface BrandMapper {
//  查询所有public List<Brand> selectAll();//查看详情Brand selectByIdBrand(int id);}
java">    <select id="selectByIdBrand" resultMap="brandResultMap">select *from tb_brand where id=#{id};</select>

select id中的id和方法名是一样的
#{id}这个就相当于原来写的问号是一样的
{}里面的和方法的参数名称保持一致就可以了

java">    @Testpublic void testSelectById() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession=sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper=sqlSession.getMapper(BrandMapper.class);//4.执行方法int id=1;Brand brand=brandMapper.selectById(id);System.out.println(brand);//5.释放资源sqlSession.close();//Mybatis完成操作三步,,,编写接口方法,编写sql,执行方法,,,,,,}
}

相比原来只需要改两行代码就可以了
而且这种测试方法,鼠标放在哪里,就运行哪个方法

在这里插入图片描述
#{id}就是?
这个就是参数占位符
参数占位符:
${}
#{}

java">    <select id="selectById" resultMap="brandResultMap">select *from tb_brand where id=${id};</select>

#{}替换为?,再给?赋值,,这个是为了防止SQL注入的
${}:直接替换为1,直接拼sql,存在SQL注入问题
所以用#{}

java">    <select id="selectById" resultMap="brandResultMap">select *from ${tableName} where id=#{id};</select>

${}用于表名和列名不固定的情况下
但还是存在SQL注入

java">    <select id="selectById" parameterType="int" resultMap="brandResultMap">select *from tb_brand where id=#{id};</select>

表示给#{id}设置为int类型
可以省略掉
因为接口那里就已经是int类型的了
在这里插入图片描述
在这里插入图片描述
因为<和插面的<冲突了
所以特殊字符的处理就是转义或者CDATA区

    <select id="selectById"  resultMap="brandResultMap">select *from tb_brand where id &lt;  #{id};</select>

<这个就是<的转义

    <select id="selectById"  resultMap="brandResultMap">select *from tb_brand where id<![CDATA[<]]>#{id};</select>

CDATA区直接CD然后提示就可以了

5.3 条件查询

select * from tb_brand where
就是输入多个条件,然后来查询
状态status=?
company_name=
写一个包含关键字的就可以查询,按理说
company_name like ?
这个是模糊查询
brand_name like ?
如何连接—》and

在这里插入图片描述
@Param(“status”)的意思就是int status中status就是要传递给占位符为status的,就是#{status}

第二个函数的意思就是,把这三个参数封装成一个对象,根据里面的getstatus方法,把对象里面的status,给status

所以参数的占位符名称要和brand对象里面的属性名称一样
不然找不到get方法

第三个就是封装成map集合
map集合键的名称要和参数占位符保持一致

<!--    条件查询--><select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brandwhere status = #{status}and company_name like #{companyName}and brand_name like #{brandName}</select>

条件查询
1.散装参数 如果有多个参数,需要使用@Param(占位符名称),因为这样可以标记,特定去使用对应的sql语句的占位符
2.对象参数
3.map集合参数

java"> List<Brand> selectByCondition(@Param("status")int status,@Param("companyName")String companyName,@Param("brandName")String brandName);
java">@Test
public void testSelectByCondition() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="华为";String brandName="华为";//这样是不行的,因为期待的是,用户输入了华为,就进行模糊匹配,所以要写模糊的表达式,用%或者_,在程序里面处理companyName="%"+companyName+"%";brandName="%"+brandName+"%";List<Brand> brands=brandMapper.selectByCondition(status,brandName,companyName);System.out.println(brands);//5.释放资源sqlSession.close();}

在这里插入图片描述

java">    List<Brand> selectByCondition(Brand brand);
java">@Test
public void testSelectByCondition() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="华为";String brandName="华为";//这样是不行的,因为期待的是,用户输入了华为,就进行模糊匹配,所以要写模糊的表达式,用%或者_,在程序里面处理companyName="%"+companyName+"%";brandName="%"+brandName+"%";Brand brand=new Brand();brand.setStatus(status);brand.setbrandName(brandName);brand.setcompanyName(companyName);List<Brand> brands=brandMapper.selectByCondition(brand);System.out.println(brands);//5.释放资源sqlSession.close();}

在这里插入图片描述

java">    List<Brand> selectByCondition(Map map);
java">@Test
public void testSelectByCondition() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="华为";String brandName="华为";//这样是不行的,因为期待的是,用户输入了华为,就进行模糊匹配,所以要写模糊的表达式,用%或者_,在程序里面处理companyName="%"+companyName+"%";brandName="%"+brandName+"%";//    Brand brand=new Brand();
//    brand.setStatus(status);
//    brand.setbrandName(brandName);
//    brand.setcompanyName(companyName);Map  map=new HashMap();map.put("status",status);//保证map键的名称和参数占位符的名称一样map.put("companyName",companyName);map.put("brandName",brandName);//List<Brand> brands=brandMapper.selectByCondition(brand);List<Brand> brands=brandMapper.selectByCondition(map);System.out.println(brands);//5.释放资源sqlSession.close();}

在这里插入图片描述

如果只想查询一个,我们只设置一个

java">    Map  map=new HashMap();map.put("status",status);//保证map键的名称和参数占位符的名称一样
//    map.put("companyName",companyName);
//    map.put("brandName",brandName);

在这里插入图片描述
那么就会查不出来
因为我们的sql语句查的是三个,有两个的值都没有设置,都是null,所以数据查不出来了,所以不灵活
所以如何动态查询呢

就是sql语句会随着用户的输入或者外部条件的变化而变化,我们称之为动态sql
如何判断用户输入没有呢,如果用户输入了,就不是null,就查询
所以这样来 if(status!=null)status=#{status}
这就是动态sql
mybatis很支持动态sql
它有很多标签支持

在这里插入图片描述

java"><!--    动态条件查询--><select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brandwhere<if test="status !=null">status = #{status}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="companyName!=null and companyName!='' ">and company_name like #{companyName}</if><if test="brandName!=null and brandName!=''">and brand_name like #{brandName}</if></select>
java">    Map  map=new HashMap();map.put("status",status);//保证map键的名称和参数占位符的名称一样map.put("companyName",companyName);map.put("brandName",brandName);

在这里插入图片描述

java">    Map  map=new HashMap();map.put("status",status);//保证map键的名称和参数占位符的名称一样map.put("companyName",companyName);
//    map.put("brandName",brandName);

在这里插入图片描述

java">    Map  map=new HashMap();
//    map.put("status",status);//保证map键的名称和参数占位符的名称一样map.put("companyName",companyName);
//    map.put("brandName",brandName);

在这里插入图片描述
但是这样就会报错
因为第一个status没了,导致sql语句的where后面直接接上了and,所以出错了,sql语法有错
处理方法就是每个if都加and,然后where后面有缓冲,就是有一个恒等式

java"><!--    动态条件查询--><select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brandwhere 1=1<if test="status !=null">and status = #{status}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="companyName!=null and companyName!='' ">and company_name like #{companyName}</if><if test="brandName!=null and brandName!=''">and brand_name like #{brandName}</if></select>

看这个1=1,其实一点用都没有,就是为了满足语法而已

java">    Map  map=new HashMap();
//    map.put("status",status);//保证map键的名称和参数占位符的名称一样map.put("companyName",companyName);
//    map.put("brandName",brandName);

在这里插入图片描述
但这个方法mbatis早就想好了,可以用where标签来替换where关键字

java">    <select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brand<where><if test="status !=null">and status = #{status}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="companyName!=null and companyName!='' ">and company_name like #{companyName}</if><if test="brandName!=null and brandName!=''">and brand_name like #{brandName}</if></where></select>

在这里插入图片描述
用where关键字的时候,如果里面只有一个条件,那么就会自动取消and,这就是它的作用

5.4 单条件动态查询

就是用户自己选择条件查询,只针对某一个条件查询,针对这个条件输入自己的关键字

在这里插入图片描述
在这里插入图片描述
这里choose就相当于switch
when就是case
otherwise就是default

java">    //单条件动态查询List<Brand> selectByConditionSingle(Brand brand);//brand对象的作用就是哪个属性有值的话,就用哪个
java">    </select><select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brandwhere<choose><when test="status!=null">status=#{status}</when><when test="companyName!=null and companyName!=''">company_name like #{companyName}</when><when test="brandName!=null and brandName!=''">brand_name like #{brandName}</when></choose></select>
java">    @Testpublic void testSelectByConditionSingle() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="华为";String brandName="华为";//这样是不行的,因为期待的是,用户输入了华为,就进行模糊匹配,所以要写模糊的表达式,用%或者_,在程序里面处理companyName="%"+companyName+"%";brandName="%"+brandName+"%";Brand brand=new Brand();brand.setStatus(status);// brand.setbrandName(brandName);//brand.setcompanyName(companyName);//List<Brand> brands=brandMapper.selectByCondition(brand);List<Brand> brands=brandMapper.selectByConditionSingle(brand);System.out.println(brands);//5.释放资源sqlSession.close();}
java">    Brand brand=new Brand();brand.setStatus(status);// brand.setbrandName(brandName);//brand.setcompanyName(companyName);

在这里插入图片描述
但万一用户一个都不选呢

java">Brand brand=new Brand();// brand.setStatus(status);// brand.setbrandName(brandName);//brand.setcompanyName(companyName);

这样就可能会出错,因为一个都没选的话,where后面就没有内容了
所以用default

java">    </select><select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brandwhere<choose><when test="status!=null">status=#{status}</when><when test="companyName!=null and companyName!=''">company_name like #{companyName}</when><when test="brandName!=null and brandName!=''">brand_name like #{brandName}</when><otherwise>1=1</otherwise></choose></select>

这里where1=1,单纯是为了满足语法

也可以这样

java">    <select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brand<where><choose><when test="status!=null">status=#{status}</when><when test="companyName!=null and companyName!=''">company_name like #{companyName}</when><when test="brandName!=null and brandName!=''">brand_name like #{brandName}</when></choose></where></select>

用where标签,和上面就是一模一样的了

5.5 添加

在这里插入图片描述

java">    //添加void add(Brand brand);

这里更改一下,status是int类型

java">    <insert id="add">insert into tb_brand(brand_name,company_name,ordered,description,status)values(#{brandName},#{companyName},#{ordered},#{description},#{status})</insert>
java">    @Testpublic void testAdd() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="波导手机";String brandName="波导";String description="手机中的战斗机";int ordered=100;Brand brand=new Brand();brand.setStatus(status);brand.setbrandName(brandName);brand.setcompanyName(companyName);brand.setDescription(description);brand.setOrdered(ordered);brandMapper.add(brand);//5.释放资源sqlSession.close();}

在这里插入图片描述
但是数据库里面并没有添加

为什么呢
因为mybatis给你关闭了事务的自动提交,所以你要手动提交才行

java">   @Testpublic void testAdd() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int status=1;String companyName="波导手机";String brandName="波导";String description="手机中的战斗机";int ordered=100;Brand brand=new Brand();brand.setStatus(status);brand.setbrandName(brandName);brand.setcompanyName(companyName);brand.setDescription(description);brand.setOrdered(ordered);brandMapper.add(brand);//提交事务sqlSession.commit();//5.释放资源sqlSession.close();}

在这里插入图片描述
如果不想手动提交事务的话
可以这样

java">        //2.获取SqlSession对象//SqlSession sqlSession = sqlSessionFactory.openSession();SqlSession sqlSession = sqlSessionFactory.openSession(true);

true这样就是自动提交了
openSession是默认开启事务的

5.6 主键返回

在这里插入图片描述

java">        brandMapper.add(brand);Integer id=brand.getId();System.out.println(id);

注意这里的id应该改为Integer,不然默认为0
这里打印出来就是null
在这里插入图片描述
所以数据库添加成功之后,数据库里面的id值无法获取出来

在这里插入图片描述
但是这里数据里里面是有数据的
但是得不到id
如何把数据库里面的id绑定到对象里面呢

java">    <insert id="add" useGeneratedKeys="true" keyProperty="id">insert into tb_brand(brand_name,company_name,ordered,description,status)values(#{brandName},#{companyName},#{ordered},#{description},#{status})</insert>

我们可以设置一个useGeneratedKeys为true
然后一个keyProperty为order对象里面主键id的名称
设置完这个,对象里面就有id值了

java">        brandMapper.add(brand);Integer id=brand.getId();System.out.println(id);

在这里插入图片描述
这就是主键返回

5.7 修改全部字段

在这里插入图片描述
就是点击编辑按钮的时候,然后就可以对所有的数据更改

java">    <update id="update">update tb_brandset brand_name=#{brandName},company_name=#{companyName},ordered=#{ordered},description=#{description},status=#{status}where id=#{id};</update>
java">    int update(Brand brand);
java">    @Testpublic void testUpdate() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象//SqlSession sqlSession = sqlSessionFactory.openSession();SqlSession sqlSession = sqlSessionFactory.openSession(true);//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int id=5;//修改第五个int status=1;String companyName="波导手机";String brandName="波导";String description="波导手机,手机中的战斗机";int ordered=200;Brand brand=new Brand();brand.setStatus(status);brand.setbrandName(brandName);brand.setcompanyName(companyName);brand.setDescription(description);brand.setOrdered(ordered);brand.setId(id);int count=brandMapper.update(brand);System.out.println(count);//提交事务sqlSession.commit();//5.释放资源sqlSession.close();}

在这里插入图片描述
在这里插入图片描述

5.8 修改动态字段

在这里插入图片描述
意思是有很多的数据,只定向的修改几个就可以了
比如修改密码,那么就只提交密码和id就可以了
如果用原来的sql语句,只提交了几个,那么其他几个就变成null了

java">        Brand brand=new Brand();Brand brand=new Brand();brand.setStatus(status);
//        brand.setbrandName(brandName);
//        brand.setcompanyName(companyName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);brand.setId(id);

我们看这个,只提交id和status
在这里插入图片描述
在这里插入图片描述

java">    <update id="update">update tb_brandset<if test="brandName!=null and brandName!=''">brand_name=#{brandName},</if><if test="companyName!=null and companyName!=''">company_name=#{companyName},</if><!--        因为ordered是Integer,所以不会为空字符串,只会为null--><if test="ordered!=null">ordered=#{ordered},</if><if test="description!=null">description=#{description},</if><if test="status!=null">status=#{status}</if>where id=#{id};</update>

这个有一点问题,第一个就是逗号的问题,如果最后一句没有执行,那么where前面就会有一个逗号
第二个就是如果全部if都没有执行,那么只有set了
这两个问题可以用set标签

java">    <update id="update">update tb_brand<set><if test="brandName!=null and brandName!=''">brand_name=#{brandName},</if><if test="companyName!=null and companyName!=''">company_name=#{companyName},</if><!--        因为ordered是Integer,所以不会为空字符串,只会为null--><if test="ordered!=null">ordered=#{ordered},</if><if test="description!=null">description=#{description},</if><if test="status!=null">status=#{status}</if></set>where id=#{id};</update>
java">        //4.执行方法int id=6;//修改第五个int status=0;String companyName="波导手机";String brandName="波导";String description="波导手机,手机中的战斗机";int ordered=200;Brand brand=new Brand();brand.setStatus(status);
//        brand.setbrandName(brandName);
//        brand.setcompanyName(companyName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);brand.setId(id);

在这里插入图片描述

5.9 删除功能

在这里插入图片描述
根据id把数据删除掉

java">    //根据id删除void deleteById(int id);
java">    <delete id="deleteById">delete from tb_brand where id=#{id};</delete>
java">    @Testpublic void testDeleteById() throws IOException {//1.获取SqlSessionFactory//不用写,自己复制String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.获取SqlSession对象//SqlSession sqlSession = sqlSessionFactory.openSession();SqlSession sqlSession = sqlSessionFactory.openSession(true);//3.获取mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4.执行方法int id=6;//修改第五个brandMapper.deleteById(id);//提交事务sqlSession.commit();//5.释放资源sqlSession.close();}

在这里插入图片描述

5.10 批量删除

就是直接删除多个数据
就是选中多个,然后一起删除,这就是复选框

就是给的多个id删除,分装成id数组,传进去就可以了
在这里插入图片描述
但是?占位符应该写几个呢,所以应该是动态sql,要有几个id,所以要遍历这个数组,用foreach
collection表示你要遍历哪个数组
item就是遍历出来的每一个元素
#{id}为占位符
那么遍历几次,就有几个?
这样就可以了

java">    //批量删除void deleteByIds(int[]ids);
java">    <delete id="deleteByIds">delete from tb_brand where idin (?,?,?);</delete>

按理说应该这样写,写很多个问号,但是有几个?呢,遍历一下就知道了

java">    <delete id="deleteByIds">delete from tb_brand where idin (<foreach collection="ids"></foreach>);</delete>

但这里不能直接写ids,因为mybatis会将数组参数分装成一个Map集合
默认:key的名称是array,val就是这个数组
所以我们要array来获取数组

java">    <delete id="deleteByIds">delete from tb_brand where idin (<foreach collection="array"></foreach>);</delete>

或者也可以这样,用@Param来改变map集合默认key的名称

java">    //批量删除void deleteByIds(@Param("ids") int[]ids);
java">    <delete id="deleteByIds">delete from tb_brand where idin (<foreach collection="ids"item="id">#{id}</foreach>);</delete>

如果数组里面有三个id,那么就会生成三个#{id},那么就会被替换成?
而且之间应该有逗号隔开

java">    <delete id="deleteByIds">delete from tb_brand where idin (<foreach collection="ids" item="id" separator=",">#{id}</foreach>);</delete>

separator就是分隔符的意思,我们用逗号分隔开

java">        //4.执行方法int[] ids={5,7,8};brandMapper.deleteByIds(ids);

在这里插入图片描述

java">    <delete id="deleteByIds">delete from tb_brand where idin <foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>;</delete>

这样写的话,in就不用写括号了
下面演示一下array

java">    //批量删除void deleteByIds(int[]ids);
java">    <delete id="deleteByIds">delete from tb_brand where idin<foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>;</delete>

这样写也是可以的

没写@,就不要写ids
反正就这两种方法

5.11 参数传递

在这里插入图片描述
传了多个参数,那么就要用@Param
要和参数的占位符名称一样

如果为多个参数的话,会分装为map集合
把这些参数一个一个装到map里面
值就是参数名
键就是这样的
map.put(“arg0”,参数值1)
map.put(“param1”,参数值1)
map.put(“arg1”,参数值2)
map.put(“param2”,参数值2)

java"> List<Brand> selectByCondition(@Param("status")int status,@Param("companyName")String companyName,@Param("brandName")String brandName);
java">    List<Brand> brands=brandMapper.selectByCondition(status,companyName,brandName);System.out.println(brands);
java">    List<Brand> selectByCondition(int status,String companyName,String brandName);

如果去掉@Param就会出错
在这里插入图片描述
他说我们可以用[arg2, arg1, arg0, param3, param1, param2]

java">    <select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brand<where><if test="status !=null">and status = #{status}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="companyName!=null and companyName!='' ">and company_name like #{companyName}</if><if test="brandName!=null and brandName!=''">and brand_name like #{brandName}</if></where></select>

改为

java">    <select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brand<where><if test="arg0 !=null">and status = #{arg0}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="arg1!=null and arg1!='' ">and company_name like #{arg1}</if><if test="arg2!=null and arg2!=''">and brand_name like #{arg2}</if></where></select>

在这里插入图片描述
然后就是parame1,也是可以的这些

java">    <select id="selectByCondition"  resultMap="brandResultMap">select *from tb_brand<where><if test="param1 !=null">and status = #{param1}</if><!--        test里面的companyName就是 #{companyName}里面的companyName--><if test="param2!=null and param2!='' ">and company_name like #{param2}</if><if test="param3!=null and param3!=''">and brand_name like #{param3}</if></where></select>

在这里插入图片描述
但是并不推荐上面两种方法,还是建议使用@Param,这个就是来替换arg0,agr1,只对第一个参数@Param,那么arg0就被替换了,而且不能使用了,以此类推

单个参数的话,如果是POJO类型,可以直接使用,属性名和参数占位符一样,不用@Param
Map集合键名和参数占位符一样就可以了,直接使用,,不用@Param
其他类型:比如定义一个intid类型,也可以直接用

Collection:建立一个map,键就是collection,值就是你传进来的
还有一个键是arg0
List也是一样的,map有三个键,Collection,arg0,list
数组的话,键就是array和arg0

但是只要你全部用@Param(修改arg0),就没有事了

5.12 注解完成增删改查

在这里插入图片描述
就是把sql语句写在注解中,而不是配置文件

意思就是方法和sql语句挨在一起了
有四个注解
但是一般只完成简单功能,复杂功能还是用配置文件
比如动态sql还是写在配置文件中好点

java">    User selectById(int id);

用这个的注解的前提就是相关的配置要注释掉

java">
<!--  resultType是别名,大小写无所谓  -->
<!--    <select id="selectById" resultType="User">-->
<!--        select * from tb_user where id =#{id};-->
<!--    </select>-->
java">    @Select("select * from tb_user where id = #{id}")User selectById(int id);
java">        User users=userMapper.selectById(3);System.out.println(users);

在这里插入图片描述

总结


http://www.ppmy.cn/news/1547566.html

相关文章

【Linux】多线程(中)

目录 一、线程互斥 1.1 互斥概念 1.2 互斥量mutex 1.3 互斥量相关API &#xff08;1&#xff09;初始化互斥量 &#xff08;2&#xff09;销毁互斥量 &#xff08;3&#xff09;互斥量加锁和解锁 1.4 互斥量原理 1.5 重入和线程安全 二、死锁 2.1 概念 2.2 造成死锁…

网约车管理:规范发展,保障安全与便捷

在数字化时代&#xff0c;网约车已成为城市出行的重要组成部分&#xff0c;为公众提供了前所未有的便捷性。然而&#xff0c;随着网约车行业的迅猛发展&#xff0c;一系列管理问题也随之浮现&#xff0c;如司机资质审核不严、车辆安全标准不一、乘客权益保护不足等。这些问题不…

c++写一个死锁并且自己解锁

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

2024 同一个网段,反弹shell四种方法【linux版本】bash、python、nc、villian反弹shell图解步骤

实验环境准备&#xff08;同一个网段下&#xff0c;我是桥接的虚拟机&#xff09; 一、bash反弹shell 二、python反弹shell 三、nc反弹shell 四、villain反弹shell 实验环境准备&#xff08;同一个网段下&#xff0c;我是桥接的虚拟机&#xff09; 一台kali的linux(攻击者)…

比特大陆/算能科技嵌入式面试题及参考答案

请描述 ubuntu 系统启动的过程。 当按下计算机电源按钮后,计算机硬件开始自检,这个过程是由 BIOS(或 UEFI)来执行的。BIOS 会检查硬件设备是否正常工作,如内存、硬盘等。之后,BIOS 会按照预设的启动顺序查找可引导的设备。 一旦找到包含 Ubuntu 系统的存储设备(如硬盘)…

嵌入式面试题练习 - 2024/11/15

欢迎找我进行职业规划&#xff0c;超值的自我投资 -> 嵌入式软件工程师一对一指导 1.设有定义char *p[]{"Shanghai","Beijing","Honkong"};则结果为j字符的表达式是&#xff08;&#xff09; A *p[1] 3 B *(p[1] 3) C *(p[3] 1) D p[3] […

一个win32 / WTL下多线程库(CThread类)的使用心得

说是多线程库&#xff0c;其实就是一个单独的.h文件&#xff0c;可以方便的放入WTL/win32工程中。 下载地址&#xff1a;CThread. 里面也简单介绍了 用法。 具体用法&#xff0c;首先自定义一个子线程类继承CThreadImpl<T>&#xff0c;注意他是个模板类。 class CMySu…

Flume1.9.0自定义拦截器

需求 1、在linux日志文件/data/log/moreInfoRes.log中一直会产生如下JSON数据&#xff1a; {"id":"14943445328940974601","uid":"840717325115457536","lat":"53.530598","lnt":"-2.5620373&qu…