面试整理(昆明)去面试就更新

1.MyBatis与MyBatis-Plus的区别?

MyBatis和MyBatis-Plus都是Java语言中非常常用的ORM框架,二者有以下区别:

1.实现方式不同

        MyBatis是基于XML或注解方式进行数据库操作的持久化框架,它提供了简单的CRUD操作及动态SQL生成等功能。

        而MyBatis-Plus是在MyBatis框架上的封装,通过对于增强简化后的API更加方便地进行开发,并且在性能、效率和易用性上都有一定的优化。

2.功能支持不同

        MyBatis-Plus相比于MyBatis提供了很多额外的功能,例如像条件构造器、代码生成器、分页插件、性能分析拦截器等实用的组件,使得开发者可以轻松快速完成业务逻辑的开发。

        而MyBatis相对较为原始,需要手写大量的SQL以完成各种功能的实现。

3.编程风格有所差异

        MyBatis的编程风格更加传统,需要定义mapper.xml文件并根据传入的参数使用相应的SQL查询语句,需要实现 Mybatis 提供的各种方法;

        而MyBatis-Plus具有许多针对CRUD进行的简化方法,通过继承BaseMapper以及使用Lambda表达式,可以让我们像SpringDataJPA类似地使用接口编程方式进行数据库操作。

下面通过代码示例来演示一下MyBatis和MyBatis-Plus的区别:

  • MyBatis的实现

首先在Mybatis中需要配置sql mapper映射文件,如下所示:

<!-- userMapper.xml -->
<mapper namespace="com.demo.dao.UserMapper">

    <select id="getUserById" parameterType="java.lang.Integer" resultType="com.demo.entity.User">
        select * from t_user where id=#{id}
    </select>

</mapper>

然后通过Mybatis的SqlSession执行相关方法实现数据查询:

SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSession sqlSession = sessionFactory.openSession();
User user = sqlSession.selectOne("com.demo.dao.UserMapper.getUserById", 1);
sqlSession.close();
  • MyBatis-Plus的实现

在MyBatis-Plus中则要比上述方式简单得多,并且提供了更加方便的CRUD操作。例如我们可以定义一个接口继承BaseMapper接口并调用其中提供的方法来操作数据库,如下所示:

public interface UserMapper extends BaseMapper<User> {

}

以下是从数据库中根据ID查询数据时,可以在Service层直接调用BaseMapper中提供的selectById()方法:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Override
    public User getUserById(Long id) {
        return baseMapper.selectById(id);
    }
}

2.对称加密和非对称加密的区别

在Java中,对称加密和非对称加密是实现数据加密的两种主要方法,它们在安全性、速度和使用场景上有着本质的区别。下面是对这两种加密方法的基本区别的详细解释:

 对称加密

1. **密钥使用**:对称加密使用相同的密钥进行加密和解密。这意味着发送方和接收方都必须拥有这个密钥,并且保持密钥的安全性。
   
2. **速度**:对称加密算法通常比非对称加密算法要快,因为它们使用的算法比较简单,适合对大量数据进行加密。
   
3. **安全性**:虽然对称加密算法本身可以非常安全,但密钥管理(尤其是密钥的分发和存储)可能会成为安全性的弱点。
   
4. **常见算法**:AES(高级加密标准)、DES(数据加密标准)、3DES(三重数据加密算法)等。

非对称加密

1. **密钥使用**:非对称加密使用一对密钥,一个是公开密钥(公钥),另一个是私有密钥(私钥)。公钥用于加密数据,而私钥用于解密数据。公钥可以公开,但私钥必须保密。
   
2. **速度**:非对称加密算法通常比对称加密慢,因为它们使用的算法更复杂,适用于小块数据的加密,如密钥交换、数字签名等。
   
3. **安全性**:非对称加密提供了更高级别的安全性,尤其是在公钥/私钥的管理和密钥交换方面,因为即使公钥被公开,没有私钥也无法解密数据。
   
4. **常见算法**:RSA、ECC(椭圆曲线加密)、Diffie-Hellman 密钥交换等。

使用场景

- **对称加密**通常用于加密大量数据的情况,因为它的加密和解密过程更快。
- **非对称加密**通常用于加密小量数据或进行安全密钥交换的场景。例如,在SSL/TLS协议中,非对称加密用于安全地交换对称密钥,然后对称密钥用于加密传输的数据。

在实际应用中,为了同时利用对称加密的高效性和非对称加密的安全性,两者往往会结合使用。例如,非对称加密用于安全地交换对称加密密钥,然后使用对称加密密钥来加密实际的数据传输。这种方法结合了两者的优点,既保证了加密过程的安全性,又提高了加密和解密的效率。

3.MyBatis-Plus关联表查询怎么写

在 MyBatis-Plus 中进行多表关联查询可以通过使用注解 @TableField 和 @TableId,以及使用 QueryWrapper 或 LambdaQueryWrapper 来实现。

以下是一个示例,假设有两个表 A 和 B,它们之间通过外键关联:

1.实体类定义

@Data
@TableName("table_a")
public class TableA {
    @TableId("id")
    private Long id;

    @TableField("name")
    private String name;

    @TableField("b_id")
    private Long bId;
}

@Data
@TableName("table_b")
public class TableB {
    @TableId("id")
    private Long id;

    @TableField("name")
    private String name;
}

2.数据库查询 

@Service
public class MyService {
    @Autowired
    private TableAMapper tableAMapper;

    public List<TableA> getTableAWithTableB() {
        QueryWrapper<TableA> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("b_id", "select id from table_b");

        return tableAMapper.selectList(queryWrapper);
    }
}

在这个示例中,通过在 TableA 实体类中添加 @TableField("b_id") 注解来映射 A 表中与 B 表关联的字段。然后在 MyService 类中通过 QueryWrapper 来创建查询条件,实现了 A 表和 B 表的联合查询。

当然,具体的多表关联查询方式还取决于你的数据库表结构和业务需求,你可以根据实际情况进行调整和修改。

4.(笔试题-选择)已知二叉树的前序遍历和中序遍历,选择后序遍历结果

二叉树的深度优先遍历有三种形式,分别是:

前序遍历:遍历顺序为根左右;

中序遍历:遍历顺序为左根右;

后序遍历:遍历顺序为左右根。

以下面一颗二叉树为例,它的不同形式的深度优先遍历的结果为:

前序遍历:1 2 4 7 3 5 6 8

中序遍历:4 7 2 1 5 3 8 6

后序遍历:7 4 2 5 8 6 3 1

 

5.(笔试题-选择)数据结构中,同时满足最快查找和删除的是:有序数组、二叉树、HashMap、有序链表?

在数据结构中,同时满足最快查找和删除的是哈希表(HashMap)。哈希表具有常数时间复杂度 O(1) 的查找和删除操作,即使在最坏情况下,其时间复杂度也是 O(n),但通常情况下能够提供非常高效的性能。相比之下,有序数组、二叉树和有序链表在查找和删除方面的性能通常较差,其时间复杂度通常为 O(log n) 或 O(n)。

6.(笔试题-选择)最快的排序算法:快速排序、堆排序、冒泡排序、归并排序?

在Java中,最快的排序算法通常是快速排序(Quick Sort)。快速排序的平均时间复杂度为 O(n log n),在最好情况下可达到 O(n log n),而在最坏情况下为 O(n^2)。尽管最坏情况下的性能可能不如其他排序算法,但在实践中,快速排序通常表现出色,尤其对于大规模数据集合。

归并排序(Merge Sort)也是一种非常有效的排序算法,其时间复杂度同样为 O(n log n),而且在任何情况下都能保持稳定的性能。

堆排序(Heap Sort)虽然具有 O(n log n) 的时间复杂度,但相比快速排序和归并排序,它通常在实践中稍显慢一些。

冒泡排序(Bubble Sort)的时间复杂度为 O(n^2),在大规模数据集合中效率较低,通常不被认为是最快的排序算法。

因此,综合考虑,快速排序和归并排序通常被认为是Java中最快的排序算法之一。

7.(笔试题-填空)TCP和ip分别在OSI模型的哪一层?

TCP(Transmission Control Protocol)和IP(Internet Protocol)位于OSI模型中的不同层级。

- TCP(传输控制协议)位于OSI模型的第四层,即传输层。它负责提供可靠的、面向连接的通信服务,确保数据的可靠传输,以及数据的分段、重组、流量控制和拥塞控制等功能。

- IP(Internet Protocol)位于OSI模型的第三层,即网络层。它负责在网络中实现主机之间的数据传输,包括寻址、路由和分片等功能。

因此,TCP负责在应用程序之间建立可靠的连接和数据传输,而IP负责在网络中的主机之间进行数据包的路由和转发。

8.(笔试题-填空)403表示什么意思?

一、什么是HTTP ERROR 403

403 Forbidden 是HTTP协议中的一个状态码(Status Code)。可以简单的理解为没有权限访问此站,服务器受到请求但拒绝提供服务。

二、HTTP 403 状态码解释大全

403.1 -执行访问禁止。

403.2 -读访问禁止。

403.3 -写访问禁止。

403.4要求SSL。

403.5 - 128要求SSL。

403.6 - IP地址被拒绝。

403.7 -客户证书要求。

403.8 -站点访问被拒绝。

403.9 -禁止:太多的客户端试图连接到Web服务器。

403.10 -禁止:Web服务器配置为拒绝执行访问。

403.11 -禁止:密码已更改。

403.12映射器拒绝访问。

403.13 -客户端证书吊销。

403.14 -目录列表被拒绝。

403.15 -禁止:客户端访问许可证超出了Web服务器的限制。

403.16客户证书不可信或无效。

403.17 -客户端证书已过期或尚未有效。

403.18 -无法在当前应用程序池中执行请求的URL。

403.19不能执行此应用程序池中的客户端的CGI应用程序。

403.20 -禁止:护照登录失败。

403.21 -禁止:源访问拒绝。

403.22 -禁止:无限深度被拒绝。

403.502 -禁止:来自同一客户端IP的请求太多;达到动态IP限制限制。

三、导致403错误的主要原因

1、你的IP被列入黑名单。

2、你在一定时间内过多地访问此网站(一般是用采集程序),被防火墙拒绝访问了。

3、网站域名解析到了空间,但空间未绑定此域名。

4、你的网页脚本文件在当前目录下没有执行权限。

5、在不允许写/创建文件的目录中执行了创建/写文件操作。

6、以http方式访问需要ssl连接的网址。

7、浏览器不支持SSL 128时访问SSL 128的连接。

8、在身份验证的过程中输入了错误的密码。

9、DNS解析错误,手动更改DNS服务器地址。

10、连接的用户过多,可以过后再试。

11、服务器繁忙,同一IP地址发送请求过多,遭到服务器智能屏蔽。

9.(笔试题-算法)判断由“(”和“)”组成的字符串是否是合理的成对出现的。

10.(笔试题)获取俩个集合的交集。

11.(笔试题)最终输出的值

    public static void main(String[] args) {

        //n=5
        System.out.println(fun(5));

    }

    public static int fun(int n){

        if (n < 2){
            return 0;
        }

        return fun(n-2) + fun(n-1);
    }

结果:0

12.map和set的区别

1.Map是键值对,Set是值的集合,当然键和值可以是任何的值

2.Map可以通过get方法获取值,而set不能因为它只有值;

3.都能通过迭代器进行for…of遍历;

4.Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

5.map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序

13.Redis的存储结构

Redis的五种数据结构

一、字符串(String)

字符串是Redis最基本的数据结构,可以存储任意类型的数据,例如文本、数字等。Redis中的字符串是二进制安全的,可以进行基于字符串的操作,如设置、获取、修改、删除等。

  • 应用场景: 单值缓存、对象缓存、计数器

  • 存储结构

  • SpringBoot中基本操作

  • @Slf4j
    @RestController
    @RequestMapping("/redis/string")
    public class RedisStringController {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @GetMapping("/set")
        public void setString() {
            redisTemplate.opsForValue().set("key", 1);
        }
    
        @GetMapping("/get")
        public void getString() {
            Object key = redisTemplate.opsForValue().get("key");
            log.info("{}", key);
            if (key.equals(1)) {
                log.info("111");
            }
            if ((Integer) key == 1) {
                log.info("Integer类型");
            }
        }
    
        @GetMapping("/delete")
        public void deleteString() {
            redisTemplate.delete("key");
        }
    }
    
    二、列表(List)

    列表是一个有序的字符串集合,可以存储多个字符串元素。列表支持在头部或尾部进行元素的插入、删除、获取等操作,还支持根据索引进行访问和修该。列表可以用于实现队列、栈等数据结构。

  • 应用场景: 公众号最新消息

  • 存储结构

  • SpringBoot中基本操作

    @RestController
    @Slf4j
    @RequestMapping("/redis/list")
    public class RedisListController {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @PostMapping("/push")
        public void pushList() {
            BoundListOperations listOps = redisTemplate.boundListOps("msg:1001");
            listOps.leftPush("123");
            listOps.leftPush("456");
            listOps.rightPush("789");
            //使用list集合
    //        List<String> list = new LinkedList<>();
    //        list.add("123");
    //        list.add("456");
    //        listOps.leftPushAll(list);
        }
    
        @PostMapping("/get")
        public void getList() {
            BoundListOperations listOps = redisTemplate.boundListOps("msg:1001");
            Object index = listOps.index(0);
            log.info("获取指定索引位置的元素: {}", index);
            List range = listOps.range(0, listOps.size() - 1);
            log.info("获取所有元素: {}", range.toString());
        }
    
        @PostMapping("/pop")
        public void popList() {
            BoundListOperations listOps = redisTemplate.boundListOps("msg:1001");
            Object leftPop = listOps.leftPop();
            log.info("从左弹出一个元素: {}", leftPop);
            Object rightPop = listOps.rightPop();
            log.info("从右弹出一个元素: {}", rightPop);
        }
    
        @PostMapping("/del")
        public void delList() {
            redisTemplate.delete("msg:1001");
        }
    }
    
    三、哈希表(Hash)

    哈希表是一个键值对的无序集合,其中每个键都是一个唯一的字符串,与一个值相关联。哈希表适用于存储对象,每个对象可以有多个属性。在哈希表中,可以对单个键或整个哈希表执行增删改查的操作。

  • 应用场景: 对象缓存、购物车

  • 存储结构

  • SpringBoot中基本操作
     

    @Slf4j
    @RestController
    @RequestMapping("/redis/hash")
    public class RedisHashController {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @PostMapping("/set")
        public void setHash() {
            BoundHashOperations hashOps = redisTemplate.boundHashOps("user");
            hashOps.put("1:username", "张三");
            hashOps.put("1:password", "123");
            //或者使用putAll
    //        Map<String, String> map = new HashMap<>();
    //        map.put("1:username", "张三");
    //        map.put("1:password", "123");
    //        hashOps.putAll(map);
            log.info("set-string");
        }
    
        @PostMapping("/get")
        public void getHash() {
            //获取所有key
            BoundHashOperations hashOps = redisTemplate.boundHashOps("user");
            Set keys = hashOps.keys();
            log.info("获取所有key: {}", keys.toString());
            //获取所有value
            List values = hashOps.values();
            log.info("获取所有value: {}", values.toString());
            //根据key获取value
            Object o = hashOps.get("1:username");
            log.info("根据key获取value: {}", o);
            //获取所有键值对集合
            Map entries = hashOps.entries();
            log.info("获取所有键值对集合: {}", entries.toString());
        }
    
        @PostMapping("/find")
        public void findHash() {
            BoundHashOperations hashOps = redisTemplate.boundHashOps("user");
            Boolean hasKey = hashOps.hasKey("1:username");
            log.info("判断hash中是否存在该键值对: {}", hasKey);
        }
    
        @PostMapping("/del")
        public void delHash() {
            //删除key(小key)
            BoundHashOperations hashOps = redisTemplate.boundHashOps("user");
            hashOps.delete("1:username");
            //直接删除hash(大key)
            redisTemplate.delete("user");
        }
    }
    
    四、集合(Set)
  • 集合是一组唯一的、无序的字符串元素的集合。集合支持添加、删除、判断元素是否存在等操作,还支持集合间的交集、并集、差集等集合运算操作。集合适用于对成员进行唯一性判断或快速查找。

  • 应用场景: 抽奖、点赞、收藏、标签、微博等平台关注模型(共同好友、可能认识的人等)

  • 存储结构

  • SpringBoot中基本操作
     

    @RestController
    @Slf4j
    @RequestMapping("/redis/set")
    public class RedisSetController {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @PostMapping("/add")
        public void addSet() {
            BoundSetOperations setOps = redisTemplate.boundSetOps("act:101");
            setOps.add("001", "002", "003");
        }
    
        @PostMapping("/member")
        public void memberSet() {
            BoundSetOperations setOps = redisTemplate.boundSetOps("act:101");
            List list = setOps.randomMembers(2);
            log.info("随机获取两个元素: {}", list.toString());
            Set members = setOps.members();
            log.info("获取所有的值: {}", members.toString());
        }
    
        @PostMapping("/find")
        public void findSet() {
            BoundSetOperations setOps = redisTemplate.boundSetOps("act:101");
            Boolean member = setOps.isMember("002");
            log.info("判断元素是否存在于set中: {}", member);
        }
    
        @PostMapping("/remove")
        public void removeSet() {
            BoundSetOperations setOps = redisTemplate.boundSetOps("act:101");
            Long remove = setOps.remove("002");
            log.info("移除指定的元素个数: {}", remove);
        }
    
        @PostMapping("/del")
        public void delSet() {
            redisTemplate.delete("act:101");
        }
    }
    
    五、有序集合(ZSet)

    有序集合是一个有序的字符串集合,每个字符串都与一个分数相关联。有序集合按照分数进行排序,可以根据分数范围或成员值进行范围查询。有序集合常用于排行榜、排序等场景。

  • 应用场景: 排行榜、带权重的任务调度

  • 存储结构

  • SpringBoot中基本操作
     

    @RestController
    @Slf4j
    @RequestMapping("/redis/zset")
    public class RedisZSetController {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @GetMapping("/add")
        public void addZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            zSetOps.add("李四", 2);
            zSetOps.add("王五", 1);
            zSetOps.add("刘留", 3);
            zSetOps.add("赵六", 4);
            zSetOps.add("张三", 6);
        }
    
        @GetMapping("/range")
        public void rangeZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            Set range = zSetOps.range(0, -1);
            log.info("获取ZSet中所有的元素:{}", range);
        }
    
        @GetMapping("/rangeByScore")
        public void rangeByScoreZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            Set range = zSetOps.rangeByScore(2, 4);
            log.info("获取ZSet中指定score范围中的元素:{}", range);
        }
    
        @GetMapping("/size")
        public void sizeZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            Long size = zSetOps.size();
            log.info("获取ZSet中元素的长度:{}", size);
        }
    
        @GetMapping("/incrementScore")
        public void incrementScoreZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            log.info("获取ZSet中增加前[张三]的score:{}", zSetOps.score("张三"));
            zSetOps.incrementScore("张三", 3);
            log.info("获取ZSet中增加后[张三]的score:{}", zSetOps.score("张三"));
        }
    
        @GetMapping("/count")
        public void countZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            Long count = zSetOps.count(2, 6);
            log.info("获取ZSet中指定score范围内的个数:{}", count);
        }
    
        @GetMapping("/remove")
        public void removeZSet() {
            BoundZSetOperations zSetOps = redisTemplate.boundZSetOps("hotspot:20230602");
            log.info("获取ZSet中移除[李四]之前的元素:{}", zSetOps.range(0,-1));
            zSetOps.remove("李四");
            log.info("获取ZSet中移除[李四]之后的元素:{}", zSetOps.range(0,-1));
        }
    }
    

14.io的了解

Java IO 体系的组成部分:BIO 和 NIO
BIO 的基本组成部分:字节流,字符流,转换流和处理流
NIO 的三大重要模块:缓冲区(Buffer),通道(Channel),选择器(Selector)以及它们的作用
NIO 与 BIO 两者的对比:同步/非同步、阻塞/非阻塞,在文件 IO 和 网络 IO 中,使用 NIO 相对于使用 BIO 有什么优势

15.说说索引

1.什么是索引?

索引是一种特殊的文件,它包含着对数据表里所有记录的引用指针

索引是一种数据结构,以协助快速查询,更新数据库中的数据

所有的实现通常使用B树接变种B+树

更通俗的说索引就相当于目录,为了方便查找书中的内容,通过对内容建立索引形成目录

索引是一个文件,它是要占用物理空间的

2.索引的优缺点?

索引的优点:

1.可以大大加快数据的检索速度,这个是创建索引的主要原因

2.通过使用索引,可以查询的过程中,使用优化隐藏器,提高系统性能

索引的缺点:

1.时间方面:创建索引和维护索引要耗费时间,具体的,当对表中的数据进行增加,删除和修改的时候,索引也要动态维护,会降低增删改的执行效率

2.空间方面:索引需要占用物理内存

3.MySQL的索引分类

单例索引
1.普通索引:MySQL中的基本索引类型,没有什么限制,允许在定义索引的列中插入重复和空值,纯属为了查询更快 ALTER TABLE table_name ADD INDEX index_name(column)

2.唯一索引:索引列中的值必须是唯一的,但是允许空值 ALTER TABLE table_name ADD UNIQUE(column)

3.主键索引:是一种特殊的唯一索引,不允许有空值

复合索引
多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用复合索引时遵循最左侧前缀集合 ALTER TABLE table_name ADD INDEX index_name(column1,column2,column3)

全文索引
解释:就是在一对文字中,通过某个关键字等,就能够到该字段所属的记录行

只有MyISAM引擎才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引

ALTER TABLE table_name ADD FULLTEXT(column)

空间索引
空间索引是对空间数据类型的字段建立索引

MySQL中的空间字段有四个,GEOMETTY,POINT,LINESTRING,POLYGON

4.索引失效

1.like以%开头的索引无效,但是like以%结尾,索引有效

2.or语句前后没有同时使用索引会失效,当且仅当or语句查询条件的前后均有索引生效

3.复合索引,使用的不是第一列索引的时候,索引失效,即最左侧匹配规则

4.数据类型出现隐式转换,比如varchar不加单引号的时候可能会自动转换成int类型,这个时候索引失效

5.在索引列上使用IS NULL或者 IS NOT NULL的时候,索引失效,因为索引是不索引空间的

6. 在索引字段上使用 NOT <> != 时候不会使用索引的,对于这样的处理只会进行全表扫描

7. 对索引字段进行计算操作,函数操作时不会使用索引

8. 当全表扫描速度比索引速度快的时候不会使用索引

16.描述一个一对多或者多对多的业务场景(最好举例多对多的情况),将表结构设计一下

比如:

学生表student:

id      name
1001    张三
1002    张四
1003    王五
1004    赵六

课程表course:

id     name   
111    java   
222    mysql

17.事务指的是什么,什么时候用到

一、什么是事务?
事务是指单个逻辑工作单元执行得一系列操作,要么都做,要么都不做,是不可分割的工作单位,是数据库环境中的的最小工作单元。
二、为什么需要事务?
事务包含了一组操作,这些操作可以是一条SQL语句、一组SQL语句或整个程序。如果其中一个操作不成功,这些操作都不会执行,前面执行的操作也会回滚原状态,用来保证数据的一致性和完整性。例如,就像银行转账,张三给李四转账,只有当张三的钱转走了,并且李四账户的钱收到了之后才会事务提交,否则事务会回滚到转账前的状态,保证数据的一致性,保证数据不会出错。
三、事务的四大特征:
1、原子性
整个事务要么成功提交要么全部失败回滚。
2、隔离性
一个事务在完成前对其他事务是不可见的,一个事务执行前就代表上一个事务一定结束了。
3、一致性
事务操作前后,数据表中的数据是不会发生变化的,直到成功提交前。
4、持久性
一旦事务提交则会永久保存在数据库当中。

18.Sql中的group by 是用来做什么的?举例说明

(1)语法:group by 字段

查询语句
select column_name(s) #字段名
[,聚合函数]
from table #表名
where #条件语句
group by column_name #字段名

说明:group by分组的字段(列名)可为多个字段,“[,聚合函数]”表示可选,分组函数group by一般与聚合函数一起使用。若不与聚合函数一起使用单纯查询是非数值列用group by有汇总取不同值的作用。

select column_name(s) #字段名
from table #表名
group by column_name #字段名
 
相当于 
 
select distinct column_name(s) #字段名
from table #表名

(2)用法:用于分组,一般用于与聚合函数进行分组聚合(求和、统计等)。

2.实例

现有一个成绩表score,学号id,姓名name,性别sex,民族nation,班级class,语文Chinese,数学math,英语English。如下表所示。

(1)获取分组信息,取不同值。

例1:分组获取班级、性别信息。

select class,sex
from score
group by class,sex
 
相当于
 
select distinct class,sex
from score

结果如下图所示。

2)与聚合函数结合使用

例2:按班级性别分组获取语数英的成绩求和。

select class,sex,
sum(Chinese) as Chinese,
sum(math) as math,
sum(English) as English
from score
group by class,sex

19.Sql中的left join 是用来做什么的?举例说明

left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录

20.java 中list 与 set 有什么区别

1. 区别:
   - Set集合中的元素是无序的,且不允许重复;List集合中的元素是有序的,允许重复。
   - Set集合通过元素的哈希码来保证元素的唯一性,因此Set集合的元素必须实现hashCode()和equals()方法;而List集合则完全依赖于元素的顺序。
   - Set集合使用的实现类有HashSet、LinkedHashSet和TreeSet;List集合使用的实现类有ArrayList、LinkedList和Vector。

2. 子类的用法和说明:
   - HashSet:使用哈希表实现,能够提供较快的插入、删除和查询速度,但不能保证元素的顺序。
   - LinkedHashSet:使用哈希表和链表实现,在HashSet的基础上额外维护了一个链表,能够保证元素的插入顺序和遍历顺序一致。
   - TreeSet:使用红黑树实现,能够对元素进行自然排序或指定排序方式排序,但插入、删除和查询速度相对较慢。
   - ArrayList:使用动态数组实现,支持随机访问和快速插入、删除元素。
   - LinkedList:使用双向链表实现,支持高效的插入、删除操作,但对于随机访问的性能较差。
   - Vector:与ArrayList类似,但是Vector是线程安全的,支持同步操作,但性能较差。

总结:Set集合适用于需要保证元素唯一性且无序的场景,List集合适用于需要保留元素顺序且可以重复的场景。子类的选择则取决于具体的需求,如对效率要求较高时可选择HashSet或ArrayList,对有序性要求高时可选择LinkedHashSet或TreeSet。

21.java 中接口与抽象类有什么区别

abstract class 和interface有什么区别?
答:

        1抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)

        2接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法

        3接口会为方法自动拼接public abstract,还会为变量自动拼接public final static

        4抽象类可以有构造方法–用来给子类创建对象,接口中没有构造方法

        5抽象类和接口都不能实例化(创建对象)

        6接口可继承接口,并可多继承接口,但类只能单继承

        7抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果

22.java中多态是什么?举例说明

首先,多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。

另外,多态是出现在具有继承关系的两个类的对象之间,所以它不像方法重载(发生在一个类中)在编译期间发生(也就是确定下来),而是在运行期间发生(确定下来)。

1.一个父类类型的引用可以指向他任何一个子类的对象

2.[相同]类域的[不同]对象执行[同一]方法的时候会有[不同]的表现

有一个比较经典的多态实例:

有一个Animal类,它有Cat,和Dog两个子类,在Animal中有个say方法,当Cat调用这个方法的时候输出的是“小猫喵喵喵”,当Dog调用这个方法时,输出的是“小狗汪汪汪”,这就是Java多态的实现。

23.java中什么时候需要使用同步锁

synchronized与Lock的对比
Lock是显式锁(手动打开和关闭锁),synchronized是隐式锁,出了作用域自动释放
Lock只有代码块锁,synchronized有代码块锁和方法锁
使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且提供了更多的子类,有良好的扩展性

24.解释SSH是什么,分别给予简要描述

SSH:
Struts(表示层)+Spring(业务层)+Hibernate(持久层Struts:
Struts是一个表示层框架,主要作用是界面展示,接收请求,分发请求。
在MVC框架中,Struts属于VC层次,负责界面表现,负责MVC关系的分发。(View:沿用JSP,HTTP,Form,Tag,Resourse ;Controller:ActionServlet,struts-config.xml,Action)
Hibernate:
Hibernate是一个持久层框架,它只负责与关系数据库的操作。
Spring:
Spring是一个业务层框架,是一个整合的框架,能够很好地黏合表示层持久层

25.简要说明Spring MVC

SpringMVC五大组件
前端控制器(DispatcherServlet)
处理器映射器(HandlerMapping)
处理器适配器(HandlerAdapter)
视图解析器(ViewReslover)
视图渲染(View)
SpringMVC执行原理
提示:DispatcherServlet的作用:接收请求,调用其它组件处理请求,响应结果,相当于转发器、中央处理器,是整个流程控制的中心

用户发送请求 至 前端控制器(DispatcherServlet);

前端控制器(DispatcherServlet)收到请求后调用处理器映射器(HandlerMapping),处理器映射器(HandlerMapping)找到具体的Controller(可以根据xml配置、注解进行查找),并将Controller返回给DispatcherServlet;

前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)。处理器适配器经过适配调用具体的Controller;(Controller–> service --> Dao --> 数据库)
Controller执行完成后返回ModelAndView,处理器适配器(HandlerAdapter)将controller执行的结果(ModelAndView)返回给前端控制器(DispatcherServlet);

提示:Model(模型数据,即Controller处理的结果,Map) View(逻辑视图名,即负责展示结果的JSP页面的名字)

.前端控制器(DispatcherServlet)将执行的结果(ModelAndView)传给视图解析器(ViewReslover)
视图解析器(ViewReslover)根据View(逻辑视图名)解析后返回具体JSP页面

前端控制器(DispatcherServlet)根据Model对View进行渲染(即将模型数据填充至视图中);(默认会存到request域中)
前端控制器(DispatcherServlet)将填充了数据的网页响应给用户。

其中整个过程中需要开发人员编写的部分有Controller、Service、Dao、View;

​​​​​​​MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范

26.递归算法是什么?什么时候用得到?

简单地说,就是如果在函数中存在着调用函数本身的情况,这种现象就叫递归。

27.设计一个产品购物车订单系统的表结?

构,包括产品表和订单表,产品表包括产品ID、产品名称、价格等字段,订单表包括订单ID、产品ID、数量、总价格等字段。下面是一个简单的产品购物车订单系统的表结构设计:

产品表(Product table):
- 产品ID(Product ID):主键,唯一标识每个产品的ID
- 产品名称(Product Name):产品的名称
- 价格(Price):产品的价格

订单表(Order table):
- 订单ID(Order ID):主键,唯一标识每个订单的ID
- 产品ID(Product ID):外键,与产品表关联,表示订单中的产品
- 数量(Quantity):订单中该产品的数量
- 总价格(Total Price):订单中该产品的总价格

通过以上表结构设计,可以实现一个简单的产品购物车订单系统,用户可以向购物车中添加产品,生成订单并计算总价格。

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值