Java之JDBC,Maven,MYBatis

前言

就是用来操作数据库的

1.JDBC快速入门

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

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=false
        String 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语句

        //执行sql
        int count=stmt.executeUpdate(sql);//executeUpdate只能用于INSERT、UPDATE、DELETE
        System.out.println(count);
        //释放资源
        stmt.close();
        conn.close();
    }
}

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

2.JDBC之API

2.1DriverManager

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

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

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

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

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

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

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

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

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

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

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

2.2 Connection

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

        String sql1="insert into emp3 values('bb',2)";//sql语句
        String sql2="insert into emp3 values('cc',1)";//sql语句
        try {
            //开始事务
            conn.setAutoCommit(false);
            //执行sql
            int 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();
        }
conn.setAutoCommit(false);

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

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

2.3 Statement

Statement有两个方法

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

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

DML语句

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

在这里插入图片描述

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

再加上这个就更完美了

DDL语句

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

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

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

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

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

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

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

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语句
        //执行sql
        ResultSet 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();
    }
}

在这里插入图片描述

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

            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就是密码

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

先这样

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

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

        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

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

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

为什么呢

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

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

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

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

PreparedStatement演示

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注入问题

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

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
要设置这个

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

2.5 数据库连接池

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

在这里插入图片描述

这个就是配置文件

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.实操

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() {
    }
}

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

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();
        
        //sql
        String sql="select * from emp4";
        
        //获取pstmt
        PreparedStatement pstmt=conn.prepareStatement(sql);
        
        //设置?参数
        
        //执行
        ResultSet rs=pstmt.executeQuery();
        
        //然后存储
            
    }
}

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

添加操作

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

修改数据

update emp4
set name=?,
	dep_id=?
where id=?

删除

delete from emp4 where id=?

4. maven

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

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

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

<?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是全选

5.MyBatis

5.1查询

在这里插入图片描述


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;


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;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brand_name='" + brand_name + '\'' +
                ", company_name='" + company_name + '\'' +
                ", ordered='" + ordered + '\'' +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}

package com.itheima.mapper;


import com.itheima.pojo.Brand;

import java.util.List;

public interface BrandMapper {
//  查询所有
    public List<Brand> selectAll();

}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace:名称空间-->
<mapper namespace="com.itheima.mapper.UserMapper">


</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//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>
public class MybatisTest {
    //测试用例
    @Test
    public 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
驼峰命名模式,那么就有可能查询不到
但是我们可以取别名

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;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", ordered='" + ordered + '\'' +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}


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

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//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,status
            from tb_brand;
        </select>
<!--    <select id="selectAll" resultType="brand">-->
<!--        select *-->
<!--        from tb_brand;-->
<!--    </select>-->
</mapper>

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


    <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

    <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查询详情
在这里插入图片描述

public interface BrandMapper {
//  查询所有
    public List<Brand> selectAll();
    
    //查看详情
    Brand selectByIdBrand(int id);

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

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

    @Test
    public 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}就是?
这个就是参数占位符
参数占位符:
${}
#{}

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

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

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

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

    <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_brand
        where 
            status = #{status}
        and company_name like #{companyName}
        and brand_name like #{brandName}
    </select>

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

 List<Brand> selectByCondition(@Param("status")int status,@Param("companyName")String companyName,@Param("brandName")String brandName);
@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();

    }

在这里插入图片描述

    List<Brand> selectByCondition(Brand brand);

@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();

    }

在这里插入图片描述

    List<Brand> selectByCondition(Map map);
@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();

    }

在这里插入图片描述

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

    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
它有很多标签支持

在这里插入图片描述

<!--    动态条件查询-->
    <select id="selectByCondition"  resultMap="brandResultMap">
        select *
        from tb_brand
        where
        <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>
    Map  map=new HashMap();
    map.put("status",status);//保证map键的名称和参数占位符的名称一样
    map.put("companyName",companyName);
    map.put("brandName",brandName);

在这里插入图片描述

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

在这里插入图片描述

    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后面有缓冲,就是有一个恒等式

<!--    动态条件查询-->
    <select id="selectByCondition"  resultMap="brandResultMap">
        select *
        from tb_brand
        where 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,其实一点用都没有,就是为了满足语法而已

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

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

    <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

    //单条件动态查询
    List<Brand> selectByConditionSingle(Brand brand);//brand对象的作用就是哪个属性有值的话,就用哪个
    </select>
    <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>
    </select>
    @Test
    public 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();

    }
    Brand brand=new Brand();
    brand.setStatus(status);
   // brand.setbrandName(brandName);
    //brand.setcompanyName(companyName);

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


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

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

    </select>
    <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>
            <otherwise>
                1=1
            </otherwise>
        </choose>
    </select>

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

也可以这样

    <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 添加

在这里插入图片描述

    //添加
    void add(Brand brand);

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

    <insert id="add">
        insert into tb_brand(brand_name,company_name,ordered,description,status)
        values(#{brandName},#{companyName},#{ordered},#{description},#{status})
    </insert>
    @Test
    public 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给你关闭了事务的自动提交,所以你要手动提交才行

   @Test
    public 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();
    }

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

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

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

5.6 主键返回

在这里插入图片描述

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

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

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

    <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值了

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

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

5.7 修改全部字段

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

    <update id="update">
        update tb_brand
        set 
            brand_name=#{brandName},
            company_name=#{companyName},
            ordered=#{ordered},
            description=#{description},
            status=#{status}
        where id=#{id};
    </update>
    int update(Brand brand);
    @Test
    public 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了

        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
在这里插入图片描述
在这里插入图片描述

    <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>
        where id=#{id};
    </update>

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

    <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>
        //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把数据删除掉

    //根据id删除
    void deleteById(int id);
    <delete id="deleteById">
        delete from tb_brand where id=#{id};
    </delete>
    @Test
    public 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}为占位符
那么遍历几次,就有几个?
这样就可以了

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

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

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

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

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

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

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

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

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

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

        //4.执行方法
        int[] ids={5,7,8};

        brandMapper.deleteByIds(ids);

在这里插入图片描述

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

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

    //批量删除
    void deleteByIds(int[]ids);
    <delete id="deleteByIds">
        delete from tb_brand where id
        in
            <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)

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

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

    <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>

改为

    <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,也是可以的这些

    <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还是写在配置文件中好点

    User selectById(int id);

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


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

在这里插入图片描述

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/917031.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Matlab的碎纸片的自动拼接复原技术

碎纸片的自动拼接复原技术 摘要&#xff1a;破碎文件的拼接在司法物证复原、历史文献修复以及军事情报获取等领域都有着重要的应用。目前发现对碎纸片的拼接大部分由人工完成&#xff0c;准确率较高&#xff0c;但耗费大量人力财力及时间&#xff0c;效率很低。随着计算机技术的…

STM32 设计的较为复杂的物联网项目,包括智能家居控制系统,涵盖了硬件和软件的详细设计。

使用 STM32 设计的较为复杂的物联网项目&#xff0c;包括智能家居控制系统&#xff0c;涵盖了硬件和软件的详细设计。 一、硬件设计 微控制器&#xff1a;选择 STM32F4 系列微控制器&#xff0c;如 STM32F407ZGT6&#xff0c;具有高性能和丰富的外设资源。 传感器模块&#x…

1.7 JS性能优化

从输入url到页面加载完成都做了些什么 输入 URL - 资源定位符 http://www.zhaowa.com - http 协议 域名解析 https://www.zhaowa.com > ip 1. 切HOST&#xff1f; > 浏览器缓存映射、系统、路由、运营商、根服务器 2. 实际的静态文件存放&#xff1f; 大流量 > 多个…

LPDDR4芯片学习(四)——DDR Training

一、ZQ Calibration DDR 学习时间 (Part B - 6)&#xff1a;DRAM ZQ 校正 - 知乎 (zhihu.com) 从原理上解释什么是DDR的ZQ校准&#xff1f; - 知乎 (zhihu.com) LPDDR4的训练(training)和校准(calibration)--ZQ校准(Calibration)_wonder_coole-腾讯云开发者社区 01 ZQ校准的…

pycharm分支提交操作

一、Pycharm拉取Git远程仓库代码 1、点击VCS > Get from Version Control 2、输入git的url&#xff0c;选择自己的项目路径 3、点击Clone&#xff0c;就拉取成功了 默认签出分支为main 选择develop签出即可进行开发工作 二、创建分支&#xff08;非必要可以不使用&#xf…

鸿蒙实战:页面跳转

文章目录 1. 实战概述2. 实现步骤2.1 创建项目2.2 准备图片素材2.3 编写首页代码2.4 创建第二个页面 3. 测试效果4. 实战总结 1. 实战概述 实战概述&#xff1a;本实战通过ArkUI框架&#xff0c;在鸿蒙系统上开发了一个简单的两页面应用。首页显示问候语和“下一页”按钮&…

IDEA部署AI代写插件

前言 Hello大家好&#xff0c;当下是AI盛行的时代&#xff0c;好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风&#xff0c;然后写实什么的&#xff0c;现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…

深入理解 Spark 中的 Shuffle

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

常用在汽车PKE无钥匙进入系统的高度集成SOC芯片:CSM2433

CSM2433是一款集成2.4GHz频段发射器、125KHz接收器和8位RISC&#xff08;精简指令集&#xff09;MCU的SOC芯片&#xff0c;用在汽车PKE无钥匙进入系统里。 什么是汽车PKE无钥匙进入系统&#xff1f; 无钥匙进入系统具有无钥匙进入并且启动的功能&#xff0c;英文名称是PKE&…

人力资源招聘系统-提升招聘效率与质量的关键工具

在当今这个竞争激烈的商业环境中&#xff0c;企业要想在市场中立于不败之地&#xff0c;关键在于拥有高素质的人才队伍。然而&#xff0c;传统的招聘方式往往效率低下&#xff0c;难以精准匹配企业需求与人才特质&#xff0c;这无疑给企业的发展带来了不小的挑战。 随着科技的飞…

R语言贝叶斯分析:INLA 、MCMC混合模型、生存分析肿瘤临床试验、间歇泉喷发时间数据应用|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p38273 多模态数据在统计学中并不罕见&#xff0c;常出现在观测数据来自两个或多个潜在群体或总体的情况。混合模型常用于分析这类数据&#xff0c;它利用不同的组件来对数据中的不同群体或总体进行建模。本质上&#xff0c;混合模型是…

算法--解决二叉树遍历问题

第一 实现树的结构 class Node(): # 构造函数&#xff0c;初始化节点对象&#xff0c;包含数据和左右子节点 def __init__(self, dataNone): self.data data # 节点存储的数据 self.left None # 左子节点&#xff0c;默认为None self.rig…

华为eNSP:MSTP

一、什么是MSTP&#xff1f; 1、MSTP是IEEE 802.1S中定义的生成树协议&#xff0c;MSTP兼容STP和RSTP&#xff0c;既可以快速收敛&#xff0c;也提供了数据转发的多个冗余路径&#xff0c;在数据转发过程中实现VLAN数据的负载均衡。 2、MSTP可以将一个或多个VLAN映射到一个Inst…

从零到一:利用 AI 开发 iOS App 《震感》的编程之旅

在网上看到一篇关于使用AI开发的编程经历&#xff0c;分享给大家 作者是如何在没有 iOS 开发经验的情况下&#xff0c;借助 AI&#xff08;如 Claude 3 模型&#xff09;成功开发并发布《震感》iOS 应用。 正文开始 2022 年 11 月&#xff0c;ChatGPT 诞生并迅速引发全球关注。…

C++__day1

1、思维导图 2、如果登录失败&#xff0c;提示用户登录失败信息&#xff0c;并且提示错误几次&#xff0c;且重新输入&#xff1b;如果输入错误三次&#xff0c;则退出系统 #include <iostream> using namespace std;int main() {string id , pswd;string user"admi…

MySQL45讲 第二十讲 幻读是什么,幻读有什么问题?

文章目录 MySQL45讲 第二十讲 幻读是什么&#xff0c;幻读有什么问题&#xff1f;一、幻读的定义二、幻读带来的问题&#xff08;一&#xff09;语义问题&#xff08;二&#xff09;数据一致性问题 三、InnoDB 解决幻读的方法四、总结 MySQL45讲 第二十讲 幻读是什么&#xff0…

web与网络编程

使用HTTP协议访问Web 通过发送请求获取服务器资源的Web浏览器等&#xff0c;被成为客户端(client)。 Web使用一种名为HTTP(超文本传输协议)的协议作为规范&#xff0c;完成从客户端到服务器端等一系列运作流程。 可以说&#xff0c;Web时建立在HTTP协议上通信的。 网络基础T…

深入理解接口测试:实用指南与最佳实践5.0(五)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

2024游戏陪玩app源码的功能介绍/线上陪玩交友上线即可运营软件平台源码搭建流程

一个完整的陪玩交友系统从概念到实现再到维护的全过程得以清晰展现。每一步都需要团队的紧密协作与细致规划&#xff0c;以确保系统既满足用户需求&#xff0c;又具备良好的稳定性和可扩展性。 基础框架 移动端开发框架&#xff1a;如uniapp&#xff0c;它支持多平台开发&…

预测AI如何提升销售绩效管理:五大方式

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…