Mybatis操作数据库的两种方式:原生API

 mybatis操作数据的两种方式:原生api和mapper代理对象

1.mybatis的api提供的方法

  •         insert() 增加 delete() 删除  update() 更新
  •         selectOne() 返回一个数据
  •         selectList() 返回多个数据,结果类型为List
  •         selectMap() 返回多个数据,结果类型为Map
  •         select() 返回特殊格式的数据(策略+回调)

原生api总结:

        1.不用写开Connection,给?存值等繁琐的jdbc代码

        2.总清单文件只写一次,子清单文件可以写多个,都放的sql语句

        3.调用原生api,指定好sql语句的id,参数类型和结果类型即可

        4.修改sql语句只需要修改子清单文件,不用修改源代码

        5.针对查询而言,返回的数据结构(集合)丰富,不用程序员把ResultSet中的数据转换为集合对象。

mapper代理对象模式:底层用法还是原生api

2.连接数据库操作流程

(1)连接池池数据源关闭所有连接(关掉老连接)

(2)开启 jdbc

(3)创建连接connection,即mysql的连接对象

(4)seting autocommit to false开链接 ,开启事务

(5)根据方法ID在user.xml的找到对应id 的sql语句   

  • preparing预编译,(statement每个造执行计划,非常耗费时间)
  •         参数、返回值

(6)事务关闭

(7)关闭jdbc

(8)将连接还到连接池内

补充说明:

1.只要异常中的sqlSession为null,就一定是清单文件中有错误

2.给mybatis项目添加日志输出

        a.导入log4j.jar

        b.在项目的类路径下添加一个log4j.properties,logging初始化, ibatis日志管理实现适配器

连接数据库的时候可能存在的编码问题:

java.sql.SQLException: Unknown initial character set index ‘255‘ received from server.-CSDN博客

3.数据库操作

select语句提供了很丰富的结果数据结构

3.1 增删改查

 rowAffect=sqlSession.insert("insertUser",user);

 rowAffect=sqlSession.delete("deleteUserById",id);

 rowAffect=sqlSession.insert("insertUser",user);

红色标注部分为id, 根据对应Id在子清单文件中找到sql语句,并执行

xxDao.java

    public int addUser(User user);
    public int deleteUser(Integer id);
    public int updateUser(User user);

xxDaoImpl.java

public int addUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.insert("insertUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int deleteUser(Integer id) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.delete("deleteUserById",id);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int updateUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.update("updateUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

user.xml子清单文件

    <!--插入用户-->
    <insert id="insertUser"
            parameterType="org.example.entity.User">
        insert into t_user(
            user_name,
            user_password,
            address)
        values(
            #{name},
            #{password},
            #{address}
        );
    </insert>
    <!--删除用户-->
    <delete id="deleteUserById"
            parameterType="java.lang.Integer">
        delete from t_user
        where id=#{id};
    </delete>
    <!--根据id更新用户-->
    <update id="updateUser"
            parameterType="org.example.entity.User">
        update t_user set
            user_name=#{name},
            user_password=#{password},
            address=#{address}
        where
            id=#{id}
    </update>

单元测试:

    @Test
    public void addUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setName("add");
        user.setPassword("654321");
        user.setAddress("测试用例");
        Integer rowAffect=userDao.addUser(user);
        System.out.println(rowAffect);
    }

    @Test
    public void deleteUser() {
        UserDao userDao=new UserDaoImpl();
        Integer rowAffect=userDao.deleteUser(3);
        System.out.println(rowAffect);
    }

    @Test
    public void updateUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setId(3);
        user.setName("addUser");
        user.setPassword("654321");
        user.setAddress("单元测试");
        Integer rowAffect=userDao.updateUser(user);
        System.out.println(rowAffect);
    }

结果展示:

增加一个数据User

​更新id=3的数据

删除id=3的数据

特别的:子清单文件中<insert>、<select>等标签并没有进行判断,Mybatis仅对语句进行判断然后执行。从底层调用来说update\insert调用的是同一个底层方法

3.2 selectOne

查询并返回一个结果

xxDao.java

   public User findUserById(Integer id);

xxDaoImpl.java

    @Override
    public User findUserById(Integer id) {
        User user=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            user=sqlSession.selectOne("findUserById",1);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return user;
    }

user.xml

   <!--根据id获得用户信息-->
    <select id="findUserById"
            resultType="org.example.entity.User"
            parameterType="java.lang.Integer">
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
        where id = #{id}
    </select>

单元测试:

    @Test
    public void findUserById() {
        UserDao userDao=new UserDaoImpl();
        User user=userDao.findUserById(1);
        System.out.println(user);
    }

结果展示:

3.3selectList

查询并返回一个List类型的结果,List里的数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

xxDao.java

    //返回list结构
    public List<User> findAllUser1();
    public List<Map<String,Object>> findAllUser2();

xxDaoImpl.java

 @Override
    public List<User> findAllUser1() {
        List<User> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser1SqlId");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

    @Override
    public List<Map<String, Object>> findAllUser2() {
        List<Map<String, Object>> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser2SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

user.xml

    <!--查所有返回list<User>-->
    <select id="findAllUser1SqlId"
            resultType="org.example.entity.User"
            >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回list<Map>-->
    <select id="findAllUser2SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser1() {
        UserDao userDao=new UserDaoImpl();
        List<User> userList=userDao.findAllUser1();
        for(User user:userList){
            System.out.println(user);
        }

    }

    @Test
    public void findAllUser2() {
        UserDao userDao=new UserDaoImpl();
        List<Map<String, Object>> userList=userDao.findAllUser2();
        for(Map<String, Object> user:userList){
            System.out.println(user.toString());
        }
    }

结果展示:

返回List<User>

返回List<Map<String,Object>>

3.4selectMap

查询并返回一个Map类型的结果,key是指定的属性,Map里的key值数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

红色表示将id指定为最外层Map的key值, 也可将其他属性设置为key值。

xxDao.java

    //返回map结构
    public Map<Integer,User> findAllUser3();
    public Map<Integer,Map<String,Object>> findAllUser4();

xxDaoImpl.java

  @Override
    public Map<Integer, User> findAllUser3() {
        Map<Integer, User> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser3SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

    @Override
    public Map<Integer, Map<String, Object>> findAllUser4() {
        Map<Integer, Map<String, Object>> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser4SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

user.xml

   <!--查所有返回Map<User>-->
    <select id="findAllUser3SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回Map<Map>-->
    <select id="findAllUser4SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser3() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,User> userMap=userDao.findAllUser3();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

    @Test
    public void findAllUser4() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,Map<String,Object>> userMap=userDao.findAllUser4();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

结果展示:

Map<String,Object>

Map<String,Map<String,Object>>

3.5select返回自定义数据结构

select()是mybatis留给程序员的自定义接口,其可以返回程序员自定义的数据结构,可以回一个map,也可以是实体对象

这里以JsonString 为指定数据结果为例进行实现

select()可以处理自定义的特殊结构,

ResultHandler<> 是带泛型的接口,我们自定义的resultHandler,如JsonResultHandler 均实现ResultHandler<>接口

其中:

@Override

public void handleResult(ResultContext<? extends User> resultContext) {}

handleResult没有返回值,通过额外的方法将结果进行返回,如 public String getJson(){}

resultHandler处理数据结构的过程:

        resultHandler中handleResult每调用一次,处理一个对象

        返回一个数据,将数据处理为指定类型

        循环调用处理结果集中的所有对象

xxDao.java

    //自定义结构返回
    public String findAllUser5();

xxDaoImpl.java

为了返回指定的数据结构,我们在resultHandler里设定返回格式。

    @Override
    public String findAllUser5() {
        String users=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //循环多次
            JsonResultHandler resultHandler=new JsonResultHandler();
            sqlSession.select("findAllUser5SqlId",resultHandler);
            users=resultHandler.getJson();
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return users;
    }
    //内部类
    class JsonResultHandler implements ResultHandler<User>{
        //用于追加内容
        StringBuilder sb=new StringBuilder("[");

        //回调一次,返回一个对象
        //结构:  ["1":{1:2,2:3},"2":{1:2,2:3}]
        @Override
        public void handleResult(ResultContext<? extends User> resultContext) {
            //获取用户数据
            User user=resultContext.getResultObject();
            //封装成json串
            sb.append("{");
            sb.append("\"id\":");
            sb.append(user.getId()+",");
            sb.append("\"name\":");
            sb.append("\""+user.getName()+"\",");
            sb.append("\"password\":");
            sb.append("\""+user.getPassword()+"\",");
            sb.append("\"address\":");
            sb.append("\""+user.getAddress()+"\"");
            sb.append("}");
            sb.append(",");
        }

        public String getJson(){
            String temp=sb.toString();
            //前包后不包
            String temp1= temp.substring(0,temp.length()-1)+"]";
            return temp1;
        }
    }

user.xml

    <!--查所有返回自定义格式-->
    <select id="findAllUser5SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

单元测试

    @Test
    public void findAllUser5() {
        UserDao userDao=new UserDaoImpl();
        String usersJson=userDao.findAllUser5();
        System.out.println(usersJson.toString());
    }

结果展示

总结:

  • Mybatis 中的 ResultHandler 相当于数据结果集的处理器,它是一个回调函数(Callback),用来处理每一行数据的结果,这个回调函数可以在查询结果处理到一定量时触发,对结果集数据进行定制化处理。
  • ResultHandler 的使用可以大幅提升数据处理的效率,当我们需要处理大量的数据时,一般会使用 ResultHandler 来进行结果的处理,避免一次查询就全部返回结果,浪费内存资源或造成 OOM。

摘自《5.7 mybatis之ResultHandler流式处理数据_resulthandler 修改导出数据-CSDN博客》

  • mybatis中的原生 api 方法,select(),实现原理是策略模式 + 方法回调,select可以返回我们自定义的数据格式,例如json

摘自《面向接口编程+策略模式+方法回调一起使用_面向接口编程中接口回调怎么写-CSDN博客》

4.设计模式

策略模式: Mybatis的select()方法底层实现是策略模式+回调

策略模式

  • 策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
  • 其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。

摘自《https://www.cnblogs.com/xuwujing/p/9954263.html》

5.补充

数据库的游标是什么,有什么用?

1.什么是游标?
        游标Cursor是处理数据的一种方法,用来查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行向前或向后浏览数据的能力;
        游标相当于一个指针,它可以指定结果中的任何位置,允许用户对指定位置的数据进行处理;
        游标可以被看作是一个临时文件,提供了在查询结果集中向前或向后浏览护具、处理结果集中数据的能力。
2.游标的作用是什么?
        游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录进行处理的机制。
        用户可以访问结果集中任意一行数据,在将游标放置到某行之后可以在该行或从该位置的行块上执行操作。
        其实就是用于存放查询出来的多条记录的一个临时变量,我们可以从这个变量中取出我们需要的信息字段。

摘自《https://www.cnblogs.com/wanyuy/p/17098457.html》

类的内部类?

内部类可以访问该类定义所在操作域的所有数据,包括私有操作域
内部类可以对该包下的其他类隐藏
内部类可以“破解”java单继承的缺陷

摘自《java----内部类(四种内部类详解)-CSDN博客》

为什么说Mybatis是面向接口编程?

面向接口编程:就是为了处理对象之间的协作关系,去实现类之间的通信,模块之间的交互等等而设计出来的编程思想。

MyBatis在采用面向接口编程时,采用实体+接口+映射文件的方式。其中接口是不需要实现类的。

摘自《Mybatis学习笔记5:面向接口编程、注解开发_面向对象编程 mybatis-CSDN博客》

摘自《MyBatis学习总结(三)---面向接口编程_mybatis技术-接口编程 实验总结-CSDN博客》

注意:

  • sql书写时,列名和属性名对应
  • 同一个命名空间下,id不同相同
  • preparedStatement可以防止sql注入
  • springjdbc同结构——rowMapper

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

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

相关文章

算法学习系列(六十):区间DP

目录 引言区间合并模板一、石子合并二、环形石子合并三、能量项链 引言 关于这个区间 D P DP DP &#xff0c;其实是有套路和模板的&#xff0c;题型的话也是变化不多&#xff0c;感觉就那几种&#xff0c;只不过有些题会用到高精度或者是要记录方案&#xff0c;所以整体来说…

为什么你总是买不到心仪的房?可能是因为你忽略了这些!

​在人生的旅途中&#xff0c;过多的选择有时并无益处。当选择变得繁多&#xff0c;我们往往容易迷失方向&#xff0c;渴望拥有所有&#xff0c;但最终可能一无所获。 对于迫切需要购房的人来说&#xff0c;他们常常面临这样的困境&#xff1a;被各种声音和推荐所包围&#xf…

STM32窗口看门狗的操作

STM32的窗口看门狗的主要功能是&#xff0c;程序过早的喂狗还有太晚喂狗&#xff0c;都会触发单片机重启&#xff0c;就是有一个时间段&#xff0c;在这个时间段内喂狗才不会触发单片机重启。 下面我就总结一下窗口看门狗的设置过程&#xff1a; 第一步&#xff1a;开启窗口看…

搭建本地yum仓库

步骤 找个地方存你的rpm包 #我创建了一个rpm文件夹存放我的rpm包 makdir -p /opt/repo/rpmcreaterepo 这个很重要&#xff0c;一定要安装 # 我的能连外网&#xff0c;所以直接yum安装&#xff0c;你的自己想办法 yum install createrepo -y创建repodata 安装了createrepo后…

day001 ~如何修改主机名

命令行方式设置主机名 # 这个很重要&#xff01;用命令改方便些 hostnamectl set-hostname ocloud-252 #查询&#xff0c;exit或logout重新登录后发现主机名换掉 hostname nmtui方式修改 nmtui 在工作中,如果机器很多,最好修改主机名做好标识不至于弄混,方便管理.

WEB后端复习——监听器、过滤器

Listener监听器 是Servlet规范中定义的一种特殊类&#xff0c;它用于监听web应用程序中的ServletContext, HttpSession和ServletRequest等域对象的创建与销毁事件&#xff0c;以及监听这些域对象中的属性发生修改的事件。 注解WebListener 1.ServletContextListener 监听Serv…

Windows使用cowaxess(goaccess)分析Nginx日志

原文网址&#xff1a;Windows使用cowaxess(goaccess)分析Nginx日志_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows安装cowaxess来分析Nginx的access.log日志的方法。 cowaxess是goaccess的Windows版本&#xff0c;cowaxess底层会调用goaccess。 GoAccess 是一个专门用来…

uniapp获取当前位置及检测授权状态——支持App、微信小程序

uniapp获取当前位置检测及定位权限——支持App、微信小程序 首先&#xff0c;祝天下母亲&#xff0c;节日快乐~ 文章目录 uniapp获取当前位置检测及定位权限——支持App、微信小程序效果图新增 兼容小程序方法manifest Tips&#xff1a; 上一篇介绍 App端 uniapp获取当前位置及…

# 电脑突然连接不上网络了,怎么办?

电脑突然连接不上网络了&#xff0c;怎么办&#xff1f; 一、原因分析&#xff1a; 1、IP 地址冲突 2、DNS 解析出现问题。 3、电脑网络设置是否打开了【移动热点】或【飞行模式】。 4、【WLAN AutoConfig】服务是否打开。 5、无线网卡驱动损坏。 6、检查 WIFI 开关是否…

新闻资讯微信小程序开发后端+php【附源码,文档说明】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

1060: 无向图的最大度计算

解法&#xff1a; #include<iostream> #include<vector> using namespace std; int arr[100][100]; int main() {int n, max 0;cin >> n;vector<int> sum(n, 0);for (int i 0; i < n; i) {for (int j 0; j < n; j) {cin >> arr[i][j];…

Web UI自动化测试--PO模式

没有PO实现的测试用例的问题: 重用性低:登录功能重复可维护性差:数据和代码混合可读性差:元素定位方法杂乱(id、xpath、css混杂)可读性差:不易识别操作的含义(特别是css和xpath语法)可维护性差:如果某个元素的属性改了,你要更改多次PO(Page Object Model)页面对象模型…

零基础学MySQL

1. 零基础学MySQL 1.1 数据库简介 1.1.1 数据库三层结构 1. 所谓安装Mysql数据库&#xff0c;就是在主机安装一个数据库管理系统(DBMS)&#xff0c;这个管理程序可以管理多个数据库。DBMS(database manage system) 2. 一个数据库中可以创建多个表,以保存数据(信息)。 3. 数据…

ASP.NET一种多商家网络商店的设计与实现

摘 要 21世纪是网络的世纪&#xff0c;电子商务随之将成为主流商业模式&#xff0c;多商家网络商店系统就是一个C2C型的电子商务系统。本文详细论述了采用ASP.NET 2005 和 SQL Server 2000等技术实现的一个多商家网络商店的过程。论文首先阐述了本设计题目的选题意义、背景&a…

其他的 框架安全:Apache Solr 远程代码漏洞.(CVE-2019-0193)

什么是 Apache Solr Apache Solr是一个开源的搜索服务&#xff0c;便用Java语言开发&#xff0c;主要基于 HTTP 和ApacheLucene 实现的。Sor是一个高性能&#xff0c;采用Java5开发&#xff0c;基于Lucene的全文搜索服务器。 目录&#xff1a; 什么是 Apache Solr 生成的漏…

Multisim 14 常见电子仪器的使用和Multisim的使用

multisim multisim&#xff0c;即电子电路仿真设计软件。Multisim是美国国家仪器&#xff08;NI&#xff09;有限公司推出的以Windows为基础的仿真工具&#xff0c;适用于板级的模拟/数字电路板的设计工作。它包含了电路原理图的图形输入、电路硬件描述语言输入方式&#xff0…

【Python项目】基于大数据的【电影市场预测分析】

技术简介&#xff1a;使用Python技术、B/S架构、MYSQL数据库等实现。 系统简介&#xff1a;系统都需要简单的安全登陆检查&#xff0c;在登陆成功之后要进行在映电影的分析、票房分析、电影数据等功能相关性的数据统计&#xff0c;为了使用方便这些统计型的数据使用图表来进行表…

C++高精度算法-加法

引子 在C++的运算中,难免会出现很大很大的数,下面是各个关键字的表示范围 但是如果要表示的数超过了long long可以表示的最大值( 2 64 2^{64} 264-1) 怎么办呢? 如果强制表示,就会溢出,这里的溢出大家可以自行百度,反正就是会出一些-5665434之类的数 现在,就要切入正…

Git 的原理与使用(上)

Git是一个分布式版本控制系统&#xff0c;它被广泛用于协作开发和管理软件项目。开发人员可以通过Git来跟踪文件的变化、协调工作、并管理项目的不同版本。 Git允许用户在不同的分支上开发新功能&#xff0c;然后合并这些分支并确保团队成员之间的工作协调一致。此外&#xff…

【大模型赋能开发者】海云安入选数世咨询LLM驱动数字安全2024——AI安全系列报告

近日&#xff0c;国内知名数字产业领域第三方调研咨询机构数世咨询发布了LLM驱动数字安全2024——AI安全系列报告。报告通过调研、公开信息收集等方式对目前十余家已具备LLM相关的应用能力安全厂商对比分析出了这一领域当前的产业现状并进行了各厂商的能力展示。 海云安凭借近…