企业面试真实题库
丞风智能科技面试(Java开发)
笔试部分
基础问答(每题5分,共40分)
-
面向对象的特性是什么?
封装、继承、多态、抽象
-
String s=new String("ChengFengIntelligent"):创建了几个对象?
两个,一个是字符串字面量"xyz"所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new String(String)创建并初始化的、内容与"xyz"相同的实例
-
Hashtable的原理,并说出HashMap与Hashtable的区别。
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
区别:
HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。
版本不同:HashMap-JDK1.2 Hashtable-JDK1.0
HashMap继承AbstractMap实现Map接口;Hashtable继承Dictionary实现Map接口
HashMap允许key或value为null,但是key为null只允许有一个;Hashtable不予许出现null
HashMap线程不同步;Hashtable线程同步
-
forward和redirect的区别。
- 从地址栏显示来说:
1)forword是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。
2)redirect是服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的地址。
2.从数据共享来说:
1)由于在整个定向的过程中用的是同一个request,因此forward会将request的信息带到被重定向的jsp或者servlet中使用。即可以共享数据
2)redirect不能共享 - 从运用的地方来说
1)forword 一般用于用户登录的时候,根据角色转发到相应的模块
2) redirect一般用于用户注销登录时返回主页面或者跳转到其他网站
4.从效率来说:
1)forword效率高,而redirect效率低 - 从本质来说:
forword转发是服务器上的行为,而redirect重定向是客户端的行为 - 从请求的次数来说:
forword只有一次请求;而redirect有两次请求
- 从地址栏显示来说:
-
多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?
多线程有两种实现方法:继承Thread类或者实现Runnable接口。
实现同步也有两种方法:一种是同步方法,另一种是同步代码块。
同步方法是在方法返回类型前面加上synchronized关键字
同步代码块是synchronized (这里写需要同步的对象){…} -
请列出Servelt的生命周期?
Sevlet从创建到销毁一共经历了四个生命周期:创建、初始化、服务、销毁
-
JSP页面传值方式有哪几种?每种传值方式的范围是什么?
客户端向服务器:
post方式(form,隐藏域)和get方式(URL,aa.jsp?param1=abc);
服务器端:
request,session,cookie,application -
使用一种排序算法对[6,9, 10,1,5]数字进行排序
冒泡排序(每一趟找出最大的)
//性能一般 let arr=[1,5,7,9,16,2,4]; //冒泡排序,每一趟找出最大的,总共比较次数为arr.length-1次,每次的比较次数为arr.length-1次,依次递减 let len = arr.length; for(let k = 0; k < len - 1; k++) { for(let m = 0; m < len - k - 1; m++) { if(arr[m] > arr[m+1]){ let val = arr[m]; arr[m] = arr[m+1]; arr[m+1] = val; } } } console.log(arr)
选择排序(假定某个位置的值是最小值)
//性能一般 var arr=[1,23,5,8,11,78,45]; let len = arr.length; for(let k = 0; k < len - 1; k++) { for(let m = k + 1; m < len; m++) { if(arr[k] > arr[m]){ let val = arr[m]; arr[m] = arr[k]; arr[k] = val; } } } console.log(arr)
-
请说出作用域public, private,protected,以及不写时的区别
不写为默认修饰符 friendly 修饰。
public:当前类、同一包中、子孙类、其他包 都可使用
protected:当前类、同一包中、子孙类 可使用
friendly:当前类、同一包中 可使用
private:仅当前类中可使用。 -
String和StringBuffer 的区别
三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用
String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String 。
当对字符串进行修改的时候,特别是字符串对象经常改变的情况下,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
-
如何把一段逗号分割的字符串转换成一个数组?
public static void main(String[] args) { String str = "abc,de,f,ghij,klmnopq"; String[] result = str.split(","); for (int i = 0; i < result.length; i++) { System.out.println(result[i]); } }
-
try{ }里有一个return语句,那么紧跟在这个try后的finally{ }里的code会不会被执行,什么时候被执行,在return前还是后?
前;
finally中的代码肯定会执行,但是会先执行try中的代码,如果try中有return,那么return的东西会先放到函数栈中,然后再执行finally中的代码,
①、如果finally中也有return,则会直接返回并终止程序,函数栈中的return不会被完成!;
②、如果finally中没有return,则在执行完finally中的代码之后,会将函数栈中的try中的return的内容返回并终止程序;
-
final, finally, finalize的区别。
final表示不可变的,它可以用来修饰类,方法和变量。
当它修饰类的时候表示该类是不能被继承的,因为抽象类就是用来被继承的,所以abstract关键字和final关键字不能共存。
当它修饰方法的时候表示该方法是不能被重写的。
当它修饰变量的时候表示该变量的值不能发生变化也就是该变量为一个常量。对于用final修饰的变量我们必须在申明它的时候赋值或者是在构造函数中给它赋值。
finally是异常处理中的一个关键字,通常的结构是这样的:
try{ } catch(){ } finally{ },
它一般用于资源释放,比如我们可以在finally块中关闭数据库连接,在这个结构中不管异常有没有发生finally中的代码都会执行。
但是finally中的代码不是一定会被执行。在以下情况下不会执行finally中的代码:
在进入try块之前程序发生异常。
在try块中调用了System.exit(0)终止了虚拟机的运行。
在try块或catch块中程序被中断,比如说死机。
finalize: 是Object类的一个方法,因为所有的类都继承自Object类,所以所有的类都有finalize方法。 在垃圾收集器将该对象清除出内存之前会先调用它的finalize方法,做一些内存清理工作,通常这部分内存是非java内存,如socket,finalize只会被调用一次。
-
什么是java序列化,如何实现Java序列化?
序列化:将 Java 对象转换成字节流的过程。
序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化
-
Java中会存在内存泄漏吗,请简单描述。
内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。
理论上来说,Java是有GC垃圾回收机制的,也就是说,不再被使用的对象,会被GC自动回收掉,自动从内存中清除。但是,即使这样,Java也还是存在着内存泄漏的情况,
1、长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露。2、如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持久外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。
数据库(每题5分,共10分)
1、请根据如下表结构写出相应的sql语句
dept表
deptno | dname | loc |
---|---|---|
10 | 教研部 | 北京 |
20 | 学工部 | 上海 |
30 | 销售部 | 深圳 |
40 | 财务部 | 广州 |
50 | 董事长 | 太原 |
emp表
empno | enare | job | mqr | hiredate | sal | comn | deptno |
---|---|---|---|---|---|---|---|
1001 | 小白 | 文员 | 1013 | 2000/12/17 | 8000 | 20 | |
1002 | 小红 | 销售员 | 1006 | 2001/2/20 | 16000 | 3000 | 20 |
1003 | 小吴 | 销售员 | 1006 | 2001/2/22 | 12500 | 5000 | 30 |
1004 | 小李 | 经理 | 1009 | 2001/4/2 | 29750 | 20 | |
1005 | 小五 | 销售员 | 1006 | 2001/9/28 | 12500 | 14000 | 30 |
1006 | 小黑 | 经理 | 1009 | 2001/5/1 | 28500 | 30 | |
1007 | 小赵 | 经理 | 1009 | 2001/9/1 | 24500 | 10 | |
1008 | 小曹 | 分析师 | 1004 | 2007/4/19 | 30000 | 20 | |
1009 | 小廖 | 董事长 | 2001/11/17 | 50000 | 10 | ||
1010 | 小肖 | 销售员 | 1006 | 2001/9/8 | 15000 | 0 | 30 |
1011 | 小龙 | 文员 | 1008 | 2007/5/23 | 11000 | 30 | |
1012 | 小彭 | 文员 | 1006 | 2001/12/3 | 9500 | 30 | |
1013 | 小于 | 分析师 | 1004 | 2001/12/3 | 30000 | 20 | |
1014 | 小黄 | 文员 | 1007 | 2002/1/23 | 13000 | 10 | |
1015 | 小杜 | 保洁员 | 1001 | 2013/5/1 | 8000 | 50000 | 50 |
salgrade表
grade | losal | hisal |
---|---|---|
1 | 7000 | 12000 |
2 | 12000 | 14000 |
3 | 14000 | 20000 |
4 | 20000 | 30000 |
5 | 90000 |
tbyear表
year | zz |
---|---|
2010 | 100 |
2011 | 150 |
2012 | 250 |
2013 | 800 |
2014 | 1000 |
1.查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。
SELECT
z.*,d.dname,d.loc
FROM dept d, (SELECT deptno, COUNT(*) cnt FROM emp GROUP BY deptno) z
WHERE z.deptno=d.deptno;
2.列出薪金比关羽高的所有员工。
SELECT *
FROM emp e
WHERE e.sal > (SELECT sal FROM emp WHERE enare='关羽')
3.列出所有员工的姓名及其直接上级的姓名。
SELECT e.enare, IFNULL(m.enare,'boss') AS leads
FROM emp e LEFT JOIN emp m
ON e.mqr=m.empno;
4.列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称。
SELECT e.empno, e.enare, d.dname
FROM emp e LEFT JOIN emp m
ON e.mqr=m.empno
LEFT JOIN dept d ON e.deptno=d.deptno
WHERE e.hiredate<m.hiredate;
5.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
SELECT e.*, d.dname
FROM emp e RIGHT JOIN dept d
ON e.deptno=d.deptno;
6.列出所有文员的姓名及其部门名称,部门的人数。
SELECT e.enare, d.dname, z.cnt
FROM emp e, (SELECT deptno, COUNT(*) cnt FROM emp GROUP BY deptno) z, dept d
WHERE e.deptno=d.deptno AND z.deptno=d.deptno AND e.job = "文员";
7.列出最低薪金大于15000的各种工作及从事此工作的员工人数。
SELECT job, COUNT(*)
FROM emp e
GROUP BY job
HAVING MIN(sal) > 15000;
8.列出在销售部工作的员工的姓名,假定不知道销售部的部门编号
SELECT e.enare
FROM emp e
WHERE e.deptno = (SELECT deptno FROM dept WHERE dname='销售部');
9.列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级。
SELECT e.*, d.dname, m.enare, s.grade
FROM emp e
NATURAL LEFT JOIN dept d
LEFT JOIN emp m ON m.empno=e.mqr
LEFT JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
WHERE e.sal > (SELECT AVG(sal) FROM emp);
10.列出与庞统从事相同工作的所有员工及部门名称。
SELECT e.*, d.dname
FROM emp e, dept d
WHERE e.deptno=d.deptno AND e.job=(SELECT job FROM emp WHERE enare='小黑');
11.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称。
SELECT e.enare, e.sal, d.dname
FROM emp e, dept d
WHERE e.deptno=d.deptno AND sal > ALL(SELECT sal FROM emp WHERE deptno=30)
12.列出在每个部门工作的员工数量、平均工资。
SELECT d.dname, e.cnt, e.avgsal
FROM (SELECT deptno, COUNT(*) cnt, AVG(sal) avgsal FROM emp GROUP BY deptno) e, dept d
WHERE e.deptno=d.deptno;
面试
日常类
- 你平时喜欢打游戏吗
- 你平时是怎么学习的
- 你学习新技术是怎么学习的
- 你是主动型学习还是被动型学习
技术类
-
程序为什么崩溃?程序崩溃怎么解决?
程序问题:出现了严重的bug;查看日志文件找出是哪个类出现报错,再根据报错提示修改bug
非程序问题
-
说出几种查询时id递增的方法,例如id从1-5
mysql语句中有四种:(1、用max函数
(2、用LAST_INSERT_ID()函数
(3、@@identity
(4、show table status
mybatis中:(1、在xml文件中插入新数据中的标签中加上keyProperty属性就是获取id
(2、直接用mybatis自带的插入方法 -
异常怎么来的、异常的处理流程、异常在哪一层处理
程序出现错误;首先在日志文件中找到异常的信息,如果是运用的开发工具在控制台中会出现;然后找到出现异常的位置,解决异常;一般抛出异常在controller层就要解决了,不然就让客户看到了
-
怎么处理异常的,异常的注解是什么。
@controllerAdvice+@ExceptionHandler注解 非常简单,它能拦截所有抛到controller层面的异常。
-
日志级别、为什么要用日志
关闭、致命、错误、警报、信息、调试、跟踪、所有;当程序出现bug时能更快速的找到问题的所在,帮助解决问题
-
spring cloud的原理
Spring Cloud 作为 Java 语言的微服务框架,它依赖于 Spring Boot,主要的特点就是简化了开发和部署的过程,简化了 Spring 复杂的配置和依赖管理,通过起步依赖和内置 Servlet 容器能够使开发者迅速搭起一个 Web 工程。所以 Spring Cloud 在开发部署上继承了 Spring Boot 的一些优点,提高其在开发和部署上的效率。
Spring Cloud 的首要目标就是通过提供一系列开发组件和框架,帮助开发者迅速搭建一个 分布式的微服务系统。Spring Cloud 提供了开发分布式微服务系统的一些常用组件,例如服务注册和 发现、配置中心、熔断器、智能路由、微代理、控制总线、全局锁、分布式会话等。
Spring Cloud组件
- Spring Cloud Config:服务配置中心,将所有的服务的配置文件放到本地仓库或者远程仓库,配置中心负责读取仓库的配置文件,其他服务向配置中心读取配置。
- Spring Cloud Netflix:它是通过包装了 Netflix 公司的微服务组件实现的,也是 Spring Cloud 核心的核心组件,包括 Eureka、Hystrix、Zuul、Ribbon等。
- Eureka:服务注册和发现组件。
- Hystrix:熔断器组件。Hystrix 通过控制服务的 API 接口的熔断来转移故障,防止微服务系统发生雪崩效应。另外,Hystrix 能够起到服务限流和服务降级的作用。使用 Hystrix Dashboard 组件监控单个服务的熔断器的状态,使用 Turbine 组件可以聚合多个服务的熔断器的状态。
- Zuul:智能路由网关组件。Netflix Zuul 能够起到智能路由和请求过滤的作用,是服 务接口统一暴露的关键模块,也是安全验证、权限控制的一道门。
- Ribbon:负载均衡组件。
- Spring Cloud OpenFeign:声明式远程调度组件。
- Spring Cloud Bus:消息总线组件,常和 Spring Cloud Config 配合使用,用于动态刷新服务的配置。
- Spring Cloud Sleuth:服务链路追踪组件,封装了 Dapper、Zipkin、Kibina 等组件,可以实时监控服务的链路调用情况。
- Spring Cloud Security:安全模块组件,是对 Spring Security 的封装,通常配合 OAuth2 使用来保护微服务系统的安全。
- Spring Cloud Consul:该组件是 Spring Cloud 对 Consul 的封装,和 Eureka 类似,它是另一个服务注册和发现组件。
- Spring Cloud Zookeeper:该组件是Spring Cloud对Zookeeper的封装,和Eureka、Consul 类似,用于服务的注册和发现。
- Spring Cloud Stream:数据流操作组件,可以封装 Redis、RabbitMQ、Kafka 等组件, 实现发送和接收消息等。
- Spring Cloud CLI:该组件是 Spring Cloud 对 Spring Boot CLI 的封装,可以让用户以命令行方式快速运行和搭建容器。
- Spring Cloud Gateway 提供了一个在Spring webflux之上构建API网关的库。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。,并为api提供横切关注点,比如:安全性、监控等。
- Spring Cloud Task:该组件基于 Spring Task,提供了任务调度和任务管理的功能
-
mybatis的xml跟java接口类怎么建立连接的
1、Mapper接口的名称和对应的Mapper.xml映射文件名称必须一致
2、Mapper.xml文件中的namespace与Mapper接口的类路径相同
3、Mapper接口中的方法名和Mapper.xml中定义的每个执行语句的id相同
4、Mapper接口中方法的输入参数类型要和Mapper.xml中定义的每个sql的parameterType的类型相同
5、Mapper接口方法的输出参数类型要和Mapper.xml中定义的每个sql的resultType的类型相同 -
mybatis的传入参数和结果集参数
parameterType和resultType
-
spring的两大核心
IoC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程)
-
在你这项目中,事务的作用是什么?用在那些地方?
事务包含一个或多个业务操作,这些操作要么都执行,要么都不执行。事务常被用来确保数据的一致性。
事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元);
-
查询的一套流程,用什么接收数据
普通方式-请求参数名和Controller方法的参数一致
对象方式-请求参数名和Controller方法中的对象的参数一致
@RequestParam注解自定义方法参数名-当请求参数名与方法参数名不一致时
HttpServletRequest方式
@PathVariable获取路径中的参数接收
@RequestBody-JSON方式接收
-
例举数据库修改约束的语句
常见的约束有:
主键约束(primary key),
外键约束(foreign),
唯一(unique),非空(not null)
默认(default)
用户自定义约束(check)
ALTER TABLE表名ADD CONSTRAINT 约束名 CHECK(列名 BETWEEN 最小值 AN 最大值) 例子 :ALTER TABLE UsersADD CONSTRAINT CK_Age CHECK(Age BETWEEN 18 AN 50)表示修改Users表中的Age字段必须大于等于18且小于等于50
-
你是怎么处理事务管理的。
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly=false) @Override public void transfer(Integer from, Integer to, Double money) {...}
-
spring常用的8大注解是那些
@Controller
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。
@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
params,headers
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@Resource和@Autowired
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
@ModelAttribute和 @SessionAttributes
代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。 @SessionAttributes即将值放到session作用域中,写在class上面。 具体示例参见下面:使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据
@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。
@requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter(“name”),它有三个常用参数:defaultValue = “0”, required = false, value = “isApp”;defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。
@ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
@Component
相当于通用的注解,当不知道一些类归到哪个层时使用,但是不建议。
@Repository
用于注解dao层,在daoImpl类上面注解。
-
什么是ioc,具体作用?
AOP的全称是Aspect-Oriented Programming,即面向切面编程(也称面向方面编程)。它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编程方式。
在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然使用OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。这样,如果想要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。
为了解决这一问题,AOP思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充。
-
请说说你在项目中怎么使用AOP?具体干了什么?
AOP的使用,使开发人员在编写业务逻辑时可以专心于核心业务,而不用过多的关注于其他业务逻辑的实现,这不但提高了开发效率,而且增强了代码的可维护性。
-
通过新增操作怎么把数据存入到数据库,把具体步骤列出来,在什么层干了什么?
controller:控制层
service:服务层
mapper:跟数据库交互
pojo:实体类
-
数据库怎么把行变成列?
关键的行转列的函数pivot出场了,通过这个函数我们把分数填充到转换的列语文、数学的列值。
-
能说说后端你会什么框架吗?
spring,springmvc,springboot,springcloud了解
-
前端到后端一整套流程是什么
pojo>mapper接口>service>controller>html
-
redis缓存你在这个项目是用来做什么的
Redis(REmote DIctionary Server) Redis是一个开源的使用ANSI C语言编写、跨平台、支持网络、可基于内存亦可持久化的日志型、Key-Value非关系型数据库,并提供多种语言的API。
Redis支持以下几种类型数据的存储:字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。
【Redis 优势】
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
-
说说你对事务的理解,分布式事务是什么样的?
数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
分布式事务是单个事件导致两个或多个不能以原子方式提交的单独数据源的突变的情况。在微服务的世界中,它变得更加复杂,因为每个服务都是一个工作单元,并且在大多数情况下,多个服务必须协同工作才能使业务成功。
-
数据库如何在表中删除多个id的内容,有几种方法
后台方法
mybatis 根据多个id查询数据 foreach标签
//根据主键ID删除一条记录 int deleteCategory(String[] categoryId); <!-- 根据主键删除一条记录 --> <delete id="deleteCategory"> delete from category where Category_ID in <foreach item="item" index="index" collection="array" open="(" separator="," close=")"> #{item} </foreach> </delete>
-
查询一万条数据的一整套流程
如果数据量超过一万条,采取循环查询思路实例
-
从sql到contrller全写出来
sql写在mapper.xml
mapper接口>service>controller
-
项目中哪些地方用了事务,事务都有哪些
[图片上传失败...(image-139e13-1646215318937)]
-
捕获异常,异常有哪些,从哪来的
[图片上传失败...(image-535032-1646215318937)]
-
mybatis的配置文件是哪个?包含哪些标签/内容?
mybatis-config.xml文件
environments标签
[图片上传失败...(image-330305-1646215318937)]
①environments
这个很好理解,根据语义也就是配置环境,使用default属性指定生效的环境
其中每个环境都有一个对应的id,比如:
②中的环境id为development,也就是开发环境。⑤中的环境id为test,也就是测试环境。③transactionManager
事务管理器,我们昨天执行增删改操作时,后面需要提交事务,这个也就是和其相对应。
④dataSource
数据源,type表示数据源的类型,此处是数据源连接池类型的。
其中这块的内容,我们可以封装到一个配置文件中:jdbc.properties
[图片上传失败...(image-a70014-1646215318937)]
使用properties标签引入jdbc配置文件。
在核心配置文件中,使用${}取出对应的属性,其中要和jdbc配置文件中的属性一一对应
settings标签
settings,设置的意思,它就好比是一个开启某某功能的开关。
其中有多种属性对应有多种功能,今天只接触一个功能:驼峰匹配
[图片上传失败...(image-171d96-1646215318937)]
typeAliases标签
之前我们在映射文件中用到java类型时,都是使用类的全限定名,书写起来非常麻烦。
就可以使用该标签解决这个问题:
[图片上传失败...(image-896ef0-1646215318937)]
①单一类型取别名
alisa:也就是别名的意思,这里的liuxiaoai就代表了前面type属性中的全限定名。
所以在映射文件中使用该别名也就相当于type中的全限定名。
②开启别名包扫描
这个也就相当于自动开启了一个包名。
我们在resultType中写入User,也就相当于自动给User加了一个包,也就是全限定名了。
mappers标签
每个映射文件都要在核心配置文件中引入,要一一对应,一共有四种引入方式:
上述是通过resource引入,其它的都不实用。
比如说通过class引入时,需要将映射文件和mapper接口放在同一个目录下。
准确说这四种都不实用,但是因为还没有学到spring框架,暂且使用resource引入。
映射文件标签
增删改查
[图片上传失败...(image-7c4925-1646215318937)]
-
核心配置文件
- application (.properties 或 .yml)
- bootstrap (.properties 或 .yml)
-
有一张表table,有id,name,把所有的id改为1,名字改为备注
update table set id=1
alter table 表名 change 旧列名 新列名 类型(长度) 约束;
-
在全国的身份证表中,我这里有一个身份证号,查询是否重复,重复的有哪些?
数据是用集合存储,按照不同的集合方法来进行查重
比如List,可以用contains()方法查询集合中是否包含当前数据
-
解释一下事务的原理?(不要讲特性)
数据库事务的隔离级别
讨论MySQL的事务处理特性的实现原理之前我们需要先了解下MySQL对MVCC的支持,关于MVCC 维基百科有如下解释。
多版本并发控制(Multiversion concurrency control, MCC 或 MVCC),是数据库管理系统常用的一种并发控制,也用于程序设计语言实现事务内存。MVCC意图解决读写锁造成的多个、长时间的读操作饿死写操作问题。每个事务读到的数据项都是一个历史快照(snapshot)并依赖于实现的隔离级别。写操作不覆盖已有数据项,而是创建一个新的版本,直至所在操作提交时才变为可见。快照隔离使得事物看到它启动时的数据状态
-
根据事务四个特性(一致性,原子性,隔离性,持久性),一一举个生活例子
1、原子性是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。
A给B转帐100元钱
2、一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNT表中aaa和bbb的存款总额为2000元。
3、多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
4、持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
即使出现了任何事故比如断电等,事务一旦提交,则持久化保存在数据库中。
-
数据库多表连接(内外连接)
1、交叉连接:
* select * from A,B; --- 获得的是两个表的笛卡尔积.
2、内连接: inner join -- inner 可以省略
* 显式内连接:select * from A inner join B on 条件;
* 隐式内连接:select * from A,B where 条件;
3、 外连接:outer join -- outer 可以省略
* 左外连接:以左表为驱动表,左边是全数据,右边可能为空
* 右外连接:以右表为驱动表,右边是全数据,左边可能为空
注意:还有 using, 但需字段名相同。 using(字段名)。
【多表查询的子查询】
一个SQL语句查询的过程中需要依赖另一个查询语句.
科创信息面试题(Java工程师)
基础问答
1.用js实现随机选取10–100之间的10个数字,存入一个数组,并排序。
<script type="text/javascript">
//首先创建一个空数组,用来放10个数字
var Array = [];
//接下来定义一个函数,这个函数是写10~100的随机数,我们现在把他封装成一个函数
function getRandom(num1,num2){
var transition = num2 - num1 + 1;//这里面的加1是为了能够取到100
var res = Math.floor(Math.random() * transition + num1);
return res;
}
//上面的代码已经获取了num1~num2的随机数
//下面是遍历出10个随机数,并把十个数用push放法放到新定义的数组里面
for(var i = 0; i < 10; i++){
Array.push(getRandom(10,100));
}
//最后用sort方法进行排序
Array.sort(function(a,b){
return a > b;
})
//打印数组Array
console.log(Array);
</script>
2.看下列代码,将会输出什么?
var foo = 1;
function test(){
console.log(foo);
var foo = 2;
console.log(foo);
}
test();
函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。
解析:输出undefined 和 2
本质:只提升声明部分
3.写一个function,清除字符串前后空格。(使用正则表达式,兼容所有)
function trim(str) {
if (str && typeof str === "string") {
return str.replace(/(^\s*)|(\s*)$/g,""); //去除前后空白符
}
}
4.将下面表格的奇数行、偶数行颜色分别设置为白色、红色、悬浮为黄色
<table class=”table”>
<tr><td>第一行</td></tr>
<tr><td>第二行</td></tr>
<tr><td>第三行</td></tr>
<tr><td>第四行</td></tr>
</table>
<style>
.table tr:nth-child(odd){
background-color:white;
}
.table tr:nth-child(even){
background-color:red;
}
.table tr:hover{
background-color:yellow;
}
</style>
5.生成时间戳的两种方法
方法一:System.currentTimeMillis();
方法二:new Date().getTime();
方法三:Calendar.getInstance().getTimeInmillis();
最快:方法一》方法二》方法三
6.用Java写冒泡排序法的例子
“冒泡排序法”可以将一个无序的数组按照从小到大的顺序或者是从大到小的顺序进行排序,是一种较为常见的排序算法,因为数据从小到大或者从大到小地到数列头或者数列末的过程称为“冒泡”。对于冒泡排序我觉得最重要的两点就是:(1)需要重新排序的次数,即循环的次数,这个是根据数组的序列的大小来定的,比如数组的大小为n的话,需要循环的次数就为(n - 1)次;(2)另外一个就是每次循环需要进行数据之间比较的次数,每次排序后可以确定出最大或者最小的那个数据,下次循环时就不用再进行比较了,所以每次进行比较的次数是(n - i);
对于一个数组无序的情况,无论是从大到小排序还是从小到大冒泡,假如是一个n个数据的数组,那么第一个数据无需跟自己进行大小比较了,那么需要进行比较的是跟余下的n - 1个数据,所以需要重新进行排序的循环次数是n - 1次,在每次循环的过程中需要进行的比较次数的确定也是一个关键,在第一次循环的过程可以确定(以从小到大为例)最大的那个数那么在下一次的循环中就不用再进行比较了。
下面这个实例是对数组进行从小到大排序:
public class BubbleSort {
public static void main(String[] args){
int array[] = {63,4,24,1,3,15};
System.out.print("array.toString()");
for(int i=0;i<array.length;i++){
System.out.print(array[i] + " ");
}
for(int i=1;i<array.length;i++){
for(int j=0;j<array.length-i;j++){
if(array[j]>array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
System.out.println();
System.out.print("array.toString()");
for(int i=0;i<array.length;i++){
System.out.print(array[i] + " ");
}
}
}
输出结果为:
初始数组为:63 4 24 1 3 15
排序后的数组为:1 3 4 15 24 63
7.Array和 ArrayList有何区别?
Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
Array 是指定固定大小的, ArrayList 是动态数组,长度动态可变,会自动扩容。不使用泛型的时候,可以添加不同类型元素。。
Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
8.==与equlas有什么区别?
1.基本数据类型和引用数据类型==的比较作用效果是不同的
1)基本数据类型 = =比较的是值是相同
2)引用数据类型 = =比较的是引用的地址是都相同
2.equals()本质上还是= = 只是很多类重写了equals()方法
equals()默认使用的是引用比较,只是很多类重写了equals()让其变成了值比较,所以通常情况下equals()是值比较
3.两个对象的hashCode()相等 那么equals()一定为true吗?
hashCode()相等不一定为true,因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
数据库类题目(SQL编程题)
Student(S#,Sname,Sage,Ssex) 学生表。
其中S#学号;Sname:学生姓名,Sage:学生年龄,Ssex:学生性别
Course(C#,Cname,T#)课程表
其中C#:课程编号,Cname:课程名称,T#:教师编号
SC(S#,C#,Score)成绩表。
其中S#:学号,C#:课程编号,Score:成绩
Teacher(T#,Tname)教师表
T#:教师编号,Tname:教师名字
- 查询所有同学的学号、姓名、选课数、总成绩
#第一种
select a.sid, a.Sname, count(b.cid), sum(case when b.Score is null then 0 else b.Score end)
from student as a
left join sc as b
on a.sid = b.sid
group by a.Sid;
#第二种
select a.sid, a.Sname, count(b.cid), sum(ifnull(b.score, 0))
from student as a
left join sc as b
on a.sid = b.sid
group by a.Sid, a.Sname;
- 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分、最低分
#第一种
SELECT DISTINCT(L.Cid) As 课程ID,L.score AS 最高分,R.score AS 最低分
FROM SC L ,SC AS R
WHERE L.Cid = R.Cid
and
L.score = (SELECT MAX(IL.score)
FROM SC AS IL,Student AS IM
WHERE L.Cid = IL.Cid and IM.Sid=IL.Sid
GROUP BY IL.Cid)
AND
R.Score = (SELECT MIN(IR.score)
FROM SC AS IR
WHERE R.Cid = IR.Cid
GROUP BY IR.Cid
);
#第二种
select cid As 课程ID ,max(score)as 最高分 ,min(score) as 最低分 from sc group by cid
-
查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
#第一种 select DISTINCT(s.sid),s.Sname,s.sage,s.ssex,s1.score 01score,s2.score 02score from Sc s1,Sc s2,Student s where s.sid=s1.sid and s1.sid=s2.sid and s1.cid='01' and s2.cid='02' and s1.score >s2.score; #第二种 select s.* , sc1.score , sc2.score from student s inner join (select * from sc where cid = '01') sc1 on s.sid = sc1.sid inner join (select * from sc where cid = '02') sc2 on s.sid = sc2.sid where sc1.score > sc2.score;
查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
select student.sid,avg(score) as avg_score,sname
from sc,student
where sc.sid = student.sid
group by sid
having avg_score>=60
拓维面试题(运维工程师、数据库工程师)
基础题
1.请简述下数据库设计的3范式。
第一范式的目标是确保每列的原子性:如果每列都是不可再分的最小数据单元(也称为最小的原子 单元),则满足第一范式(1NF)
第二范式首先满足第一范式,并且表中非主键列不存在对主键的部分依赖。 第二范式要求每个表只描述一 件事情
第三范式定义是,满足第二范式,并且表中的列不存在对非主键列的传递依赖。除了主键订单编 号外,顾客姓名依赖于非主键顾客编号
2.简述Oracle中DML、DDL、DCL的使用。
- dml 数据操纵语言,如 select、update、delete、insert
- ddl 数据定义语言,如 create table 、drop table
- dcl 数据控制语言,如 commit、rollback、grant、invoke
3.请列举下SQL语句中有哪些聚合函数?
AVG 返回指定组中的平均值,空值被忽略
COUNT 返回指定组中项目的数量
MAX 返回指定数据的最大值
MIN 返回指定数据的最小值
SUM 返回指定数据的和,只能用于数字列,空值被忽略
4.请列举多表关联查询的方式,关键字分别是什么?
内链接(INNER JOIN)
外链接
左外连接( LEFT[OUTER]JOIN)
右外连接(RIGHT[OUTER]JOIN)
全外链接(FULL[OUTER]JOIN)
交叉连接/笛卡尔积(CROSS JOIN)
5.Oracle存储过程包含哪三部分,并写出程序过程的语法。
过程声明,执行过程部分,存储过程异常
无参程序过程语法
create or replace procedure NoParPro
as ;
begin
;
exception //存储过程异常
;
end;
带参存储过程实例
create or replace procedure queryempname(sfindno emp.empno%type) as
sName emp.ename%type;
sjob emp.job%type;
begin
....
exception
....
end;
SQL实操题
数据结构和模拟数据如下表所示:
C表为课程表
CNO | CNAME | CTEACHER |
---|---|---|
1 | 1 | 刘老师 |
2 | 2 | 黄老师 |
3 | 3 | 李老师 |
4 | 4 | 肖老师 |
SC表为成绩表
SNO | CNO | SCGRADE |
---|---|---|
1 | 1 | 50 |
1 | 2 | 90 |
1 | 3 | 80 |
2 | 1 | 55 |
2 | 2 | 68 |
2 | 3 | 80 |
2 | 4 | 90 |
3 | 1 | 88 |
3 | 3 | 90 |
4 | 3 | 40 |
4 | 4 | 70 |
5 | 2 | 99 |
S表为学生表
SNO | SNAME |
---|---|
1 | 王才 |
2 | 李一 |
3 | 昊二 |
4 | Kevin |
5 | Henry |
1.请创建课程表C,并插入数据,写出具体的SQL语句
CREATE TABLE `c` (
`CNO` int(0) NOT NULL,
`CNAME` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`CTEACHER` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
PRIMARY KEY (`CNO`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
INSERT INTO `c` VALUES (1, '1', '刘老师');
INSERT INTO `c` VALUES (2, '2', '黄老师');
INSERT INTO `c` VALUES (3, '3', '李老师');
INSERT INTO `c` VALUES (4, '4', '肖老师');
2.查询选修了课程的学员人数。
#第一种
SELECT COUNT(*)
FROM S
WHERE EXISTS( SELECT * FROM SC WHERE SC.SNO = S.SNO )
#第二种
SELECT COUNT(DISTINCT SNO) FROM SC
3.查询最低分数大于60分,最高分数小于95分的学生的编号。
SELECT sc.SNO
FROM SC
GROUP BY sc.SNO
HAVING min(SC.SCGRADE) >60 and max(SC.SCGRADE) < 95
4.查询成绩比该课程平均成绩低的同学的成绩表
select * from sc a
where a.SCGRADE<(select avg(b.SCGRADE)
from sc b
where a.cno=b.cno)
5.查询选修某课程的同学人数多于2人的课程号,课程名,教师姓名
SELECT c.*
FROM c,sc
WHERE c.CNO=sc.CNO
GROUP BY sc.cno
HAVING COUNT(sc.SNO)>2
6.横向列出每个学生的成绩,如学号、课程1成绩、课程2成绩、课程3成绩、课程4成绩。
SELECT SNO,
IFNULL(avg(case when sc.CNO = 1 then SCGRADE end),0) as 课程1成绩,
IFNULL(avg(case when sc.CNO = 2 then SCGRADE end),0) as 课程2成绩,
IFNULL(avg(case when sc.CNO = 3 then SCGRADE end),0) as 课程3成绩,
IFNULL(avg(case when sc.CNO = 4 then SCGRADE end),0) as 课程4成绩
FROM sc
GROUP BY SNO