企業(yè)面試真實題庫
丞風智能科技面試(Java開發(fā))
筆試部分
基礎問答(每題5分,共40分)
-
面向對象的特性是什么?
封裝、繼承、多態(tài)、抽象
-
String s=new String("ChengFengIntelligent"):創(chuàng)建了幾個對象?
兩個,一個是字符串字面量"xyz"所對應的、駐留(intern)在一個全局共享的字符串常量池中的實例,另一個是通過new String(String)創(chuàng)建并初始化的、內容與"xyz"相同的實例
-
Hashtable的原理,并說出HashMap與Hashtable的區(qū)別。
哈希表(Hash table,也叫散列表),是根據(jù)關鍵碼值(Key value)而直接進行訪問的數(shù)據(jù)結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表。
區(qū)別:
HashTable類和HashMap用法幾乎一樣,底層實現(xiàn)幾乎一樣,只不過HashTable的方法添加了synchronized關鍵字確保線程同步檢查,效率較低。
版本不同:HashMap-JDK1.2 Hashtable-JDK1.0
HashMap繼承AbstractMap實現(xiàn)Map接口;Hashtable繼承Dictionary實現(xiàn)Map接口
HashMap允許key或value為null,但是key為null只允許有一個;Hashtable不予許出現(xiàn)null
HashMap線程不同步;Hashtable線程同步
-
forward和redirect的區(qū)別。
- 從地址欄顯示來說:
1)forword是服務器內部的重定向,服務器直接訪問目標地址的 url網址,把里面的東西讀取出來,但是客戶端并不知道,因此用forward的話,客戶端瀏覽器的網址是不會發(fā)生變化的。
2)redirect是服務器根據(jù)邏輯,發(fā)送一個狀態(tài)碼,告訴瀏覽器重新去請求那個地址,所以地址欄顯示的是新的地址。
2.從數(shù)據(jù)共享來說:
1)由于在整個定向的過程中用的是同一個request,因此forward會將request的信息帶到被重定向的jsp或者servlet中使用。即可以共享數(shù)據(jù)
2)redirect不能共享 - 從運用的地方來說
1)forword 一般用于用戶登錄的時候,根據(jù)角色轉發(fā)到相應的模塊
2) redirect一般用于用戶注銷登錄時返回主頁面或者跳轉到其他網站
4.從效率來說:
1)forword效率高,而redirect效率低 - 從本質來說:
forword轉發(fā)是服務器上的行為,而redirect重定向是客戶端的行為 - 從請求的次數(shù)來說:
forword只有一次請求;而redirect有兩次請求
- 從地址欄顯示來說:
-
多線程有幾種實現(xiàn)方法,都是什么?同步有幾種實現(xiàn)方法,都是什么?
多線程有兩種實現(xiàn)方法:繼承Thread類或者實現(xiàn)Runnable接口。
實現(xiàn)同步也有兩種方法:一種是同步方法,另一種是同步代碼塊。
同步方法是在方法返回類型前面加上synchronized關鍵字
同步代碼塊是synchronized (這里寫需要同步的對象){…} -
請列出Servelt的生命周期?
Sevlet從創(chuàng)建到銷毀一共經歷了四個生命周期:創(chuàng)建、初始化、服務、銷毀
-
JSP頁面?zhèn)髦捣绞接心膸追N?每種傳值方式的范圍是什么?
客戶端向服務器:
post方式(form,隱藏域)和get方式(URL,aa.jsp?param1=abc);
服務器端:
request,session,cookie,application -
使用一種排序算法對[6,9, 10,1,5]數(shù)字進行排序
冒泡排序(每一趟找出最大的)
//性能一般 let arr=[1,5,7,9,16,2,4]; //冒泡排序,每一趟找出最大的,總共比較次數(shù)為arr.length-1次,每次的比較次數(shù)為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,以及不寫時的區(qū)別
不寫為默認修飾符 friendly 修飾。
public:當前類、同一包中、子孫類、其他包 都可使用
protected:當前類、同一包中、子孫類 可使用
friendly:當前類、同一包中 可使用
private:僅當前類中可使用。 -
String和StringBuffer 的區(qū)別
三者共同之處:都是final類,不允許被繼承,主要是從性能和安全性上考慮的,因為這幾個類都是經常被使用著,且考慮到防止其中的參數(shù)被參數(shù)修改影響到其他的應用
String 是不可變的對象, 因此在每次對 String 類型進行改變的時候其實都等同于生成了一個新的 String 對象,然后將指針指向新的 String 對象,這樣不僅效率低下,而且大量浪費有限的內存空間,所以經常改變內容的字符串最好不要用 String 。
當對字符串進行修改的時候,特別是字符串對象經常改變的情況下,需要使用 StringBuffer 和 StringBuilder 類。
和 String 類不同的是,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產生新的未使用對象。
StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問)。
由于 StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的情況下,則必須使用 StringBuffer 類。
-
如何把一段逗號分割的字符串轉換成一個數(shù)組?
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會不會被執(zhí)行,什么時候被執(zhí)行,在return前還是后?
前;
finally中的代碼肯定會執(zhí)行,但是會先執(zhí)行try中的代碼,如果try中有return,那么return的東西會先放到函數(shù)棧中,然后再執(zhí)行finally中的代碼,
①、如果finally中也有return,則會直接返回并終止程序,函數(shù)棧中的return不會被完成??;
②、如果finally中沒有return,則在執(zhí)行完finally中的代碼之后,會將函數(shù)棧中的try中的return的內容返回并終止程序;
-
final, finally, finalize的區(qū)別。
final表示不可變的,它可以用來修飾類,方法和變量。
當它修飾類的時候表示該類是不能被繼承的,因為抽象類就是用來被繼承的,所以abstract關鍵字和final關鍵字不能共存。
當它修飾方法的時候表示該方法是不能被重寫的。
當它修飾變量的時候表示該變量的值不能發(fā)生變化也就是該變量為一個常量。對于用final修飾的變量我們必須在申明它的時候賦值或者是在構造函數(shù)中給它賦值。
finally是異常處理中的一個關鍵字,通常的結構是這樣的:
try{ } catch(){ } finally{ },
它一般用于資源釋放,比如我們可以在finally塊中關閉數(shù)據(jù)庫連接,在這個結構中不管異常有沒有發(fā)生finally中的代碼都會執(zhí)行。
但是finally中的代碼不是一定會被執(zhí)行。在以下情況下不會執(zhí)行finally中的代碼:
在進入try塊之前程序發(fā)生異常。
在try塊中調用了System.exit(0)終止了虛擬機的運行。
在try塊或catch塊中程序被中斷,比如說死機。
finalize: 是Object類的一個方法,因為所有的類都繼承自Object類,所以所有的類都有finalize方法。 在垃圾收集器將該對象清除出內存之前會先調用它的finalize方法,做一些內存清理工作,通常這部分內存是非java內存,如socket,finalize只會被調用一次。
-
什么是java序列化,如何實現(xiàn)Java序列化?
序列化:將 Java 對象轉換成字節(jié)流的過程。
序列化的實現(xiàn):類實現(xiàn) Serializable 接口,這個接口沒有需要實現(xiàn)的方法。實現(xiàn) Serializable 接口是為了告訴 jvm 這個類的對象可以被序列化
-
Java中會存在內存泄漏嗎,請簡單描述。
內存泄漏是指不再被使用的對象或者變量一直被占據(jù)在內存中。
理論上來說,Java是有GC垃圾回收機制的,也就是說,不再被使用的對象,會被GC自動回收掉,自動從內存中清除。但是,即使這樣,Java也還是存在著內存泄漏的情況,
1、長生命周期的對象持有短生命周期對象的引用就很可能發(fā)生內存泄露。2、如果一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄露。
數(shù)據(jù)庫(每題5分,共10分)
1、請根據(jù)如下表結構寫出相應的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.查出至少有一個員工的部門。顯示部門編號、部門名稱、部門位置、部門人數(shù)。
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.列出所有文員的姓名及其部門名稱,部門的人數(shù)。
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的各種工作及從事此工作的員工人數(shù)。
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.列出與龐統(tǒng)從事相同工作的所有員工及部門名稱。
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.列出在每個部門工作的員工數(shù)量、平均工資。
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;
面試
日常類
- 你平時喜歡打游戲嗎
- 你平時是怎么學習的
- 你學習新技術是怎么學習的
- 你是主動型學習還是被動型學習
技術類
-
程序為什么崩潰?程序崩潰怎么解決?
程序問題:出現(xiàn)了嚴重的bug;查看日志文件找出是哪個類出現(xiàn)報錯,再根據(jù)報錯提示修改bug
非程序問題
-
說出幾種查詢時id遞增的方法,例如id從1-5
mysql語句中有四種:(1、用max函數(shù)
(2、用LAST_INSERT_ID()函數(shù)
(3、@@identity
(4、show table status
mybatis中:(1、在xml文件中插入新數(shù)據(jù)中的標簽中加上keyProperty屬性就是獲取id
(2、直接用mybatis自帶的插入方法 -
異常怎么來的、異常的處理流程、異常在哪一層處理
程序出現(xiàn)錯誤;首先在日志文件中找到異常的信息,如果是運用的開發(fā)工具在控制臺中會出現(xiàn);然后找到出現(xiàn)異常的位置,解決異常;一般拋出異常在controller層就要解決了,不然就讓客戶看到了
-
怎么處理異常的,異常的注解是什么。
@controllerAdvice+@ExceptionHandler注解 非常簡單,它能攔截所有拋到controller層面的異常。
-
日志級別、為什么要用日志
關閉、致命、錯誤、警報、信息、調試、跟蹤、所有;當程序出現(xiàn)bug時能更快速的找到問題的所在,幫助解決問題
-
spring cloud的原理
Spring Cloud 作為 Java 語言的微服務框架,它依賴于 Spring Boot,主要的特點就是簡化了開發(fā)和部署的過程,簡化了 Spring 復雜的配置和依賴管理,通過起步依賴和內置 Servlet 容器能夠使開發(fā)者迅速搭起一個 Web 工程。所以 Spring Cloud 在開發(fā)部署上繼承了 Spring Boot 的一些優(yōu)點,提高其在開發(fā)和部署上的效率。
Spring Cloud 的首要目標就是通過提供一系列開發(fā)組件和框架,幫助開發(fā)者迅速搭建一個 分布式的微服務系統(tǒng)。Spring Cloud 提供了開發(fā)分布式微服務系統(tǒng)的一些常用組件,例如服務注冊和 發(fā)現(xiàn)、配置中心、熔斷器、智能路由、微代理、控制總線、全局鎖、分布式會話等。Spring Cloud組件
- Spring Cloud Config:服務配置中心,將所有的服務的配置文件放到本地倉庫或者遠程倉庫,配置中心負責讀取倉庫的配置文件,其他服務向配置中心讀取配置。
- Spring Cloud Netflix:它是通過包裝了 Netflix 公司的微服務組件實現(xiàn)的,也是 Spring Cloud 核心的核心組件,包括 Eureka、Hystrix、Zuul、Ribbon等。
- Eureka:服務注冊和發(fā)現(xiàn)組件。
- Hystrix:熔斷器組件。Hystrix 通過控制服務的 API 接口的熔斷來轉移故障,防止微服務系統(tǒng)發(fā)生雪崩效應。另外,Hystrix 能夠起到服務限流和服務降級的作用。使用 Hystrix Dashboard 組件監(jiān)控單個服務的熔斷器的狀態(tài),使用 Turbine 組件可以聚合多個服務的熔斷器的狀態(tài)。
- Zuul:智能路由網關組件。Netflix Zuul 能夠起到智能路由和請求過濾的作用,是服 務接口統(tǒng)一暴露的關鍵模塊,也是安全驗證、權限控制的一道門。
- Ribbon:負載均衡組件。
- Spring Cloud OpenFeign:聲明式遠程調度組件。
- Spring Cloud Bus:消息總線組件,常和 Spring Cloud Config 配合使用,用于動態(tài)刷新服務的配置。
- Spring Cloud Sleuth:服務鏈路追蹤組件,封裝了 Dapper、Zipkin、Kibina 等組件,可以實時監(jiān)控服務的鏈路調用情況。
- Spring Cloud Security:安全模塊組件,是對 Spring Security 的封裝,通常配合 OAuth2 使用來保護微服務系統(tǒng)的安全。
- Spring Cloud Consul:該組件是 Spring Cloud 對 Consul 的封裝,和 Eureka 類似,它是另一個服務注冊和發(fā)現(xiàn)組件。
- Spring Cloud Zookeeper:該組件是Spring Cloud對Zookeeper的封裝,和Eureka、Consul 類似,用于服務的注冊和發(fā)現(xiàn)。
- Spring Cloud Stream:數(shù)據(jù)流操作組件,可以封裝 Redis、RabbitMQ、Kafka 等組件, 實現(xiàn)發(fā)送和接收消息等。
- Spring Cloud CLI:該組件是 Spring Cloud 對 Spring Boot CLI 的封裝,可以讓用戶以命令行方式快速運行和搭建容器。
- Spring Cloud Gateway 提供了一個在Spring webflux之上構建API網關的庫。它旨在為微服務架構提供一種簡單有效的統(tǒng)一的 API 路由管理方式。,并為api提供橫切關注點,比如:安全性、監(jiān)控等。
- Spring Cloud Task:該組件基于 Spring Task,提供了任務調度和任務管理的功能
-
mybatis的xml跟java接口類怎么建立連接的
1、Mapper接口的名稱和對應的Mapper.xml映射文件名稱必須一致
2、Mapper.xml文件中的namespace與Mapper接口的類路徑相同
3、Mapper接口中的方法名和Mapper.xml中定義的每個執(zhí)行語句的id相同
4、Mapper接口中方法的輸入參數(shù)類型要和Mapper.xml中定義的每個sql的parameterType的類型相同
5、Mapper接口方法的輸出參數(shù)類型要和Mapper.xml中定義的每個sql的resultType的類型相同 -
mybatis的傳入參數(shù)和結果集參數(shù)
parameterType和resultType
-
spring的兩大核心
IoC(Inverse of Control 控制反轉)和AOP(Aspect Oriented Programming 面向切面編程)
-
在你這項目中,事務的作用是什么?用在那些地方?
事務包含一個或多個業(yè)務操作,這些操作要么都執(zhí)行,要么都不執(zhí)行。事務常被用來確保數(shù)據(jù)的一致性。
事務:是數(shù)據(jù)庫操作的最小工作單元,是作為單個邏輯工作單元執(zhí)行的一系列操作;這些操作作為一個整體一起向系統(tǒng)提交,要么都執(zhí)行、要么都不執(zhí)行;事務是一組不可再分割的操作集合(工作邏輯單元);
-
查詢的一套流程,用什么接收數(shù)據(jù)
普通方式-請求參數(shù)名和Controller方法的參數(shù)一致
對象方式-請求參數(shù)名和Controller方法中的對象的參數(shù)一致
@RequestParam注解自定義方法參數(shù)名-當請求參數(shù)名與方法參數(shù)名不一致時
HttpServletRequest方式
@PathVariable獲取路徑中的參數(shù)接收
@RequestBody-JSON方式接收
-
例舉數(shù)據(jù)庫修改約束的語句
常見的約束有:
主鍵約束(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 分發(fā)的請求,它把用戶請求的數(shù)據(jù)經過業(yè)務處理層處理之后封裝成一個Model ,然后再把該Model 返回給對應的View 進行展示。
@RequestMapping
RequestMapping是一個用來處理請求地址映射的注解,可用于類或方法上。用于類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。
params,headers
params: 指定request中必須包含某些參數(shù)值是,才讓該方法處理。
headers: 指定request中必須包含某些指定的header值,才能讓該方法處理請求。
@Resource和@Autowired
@Resource和@Autowired都是做bean的注入時使用,其實@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要導入,但是Spring支持該注解的注入。
@ModelAttribute和 @SessionAttributes
代表的是:該Controller的所有方法在調用前,先執(zhí)行此@ModelAttribute方法,可用于注解和方法參數(shù)中,可以把這個@ModelAttribute特性,應用在BaseController當中,所有的Controller繼承BaseController,即可實現(xiàn)在調用Controller時,先執(zhí)行@ModelAttribute方法。 @SessionAttributes即將值放到session作用域中,寫在class上面。 具體示例參見下面:使用 @ModelAttribute 和 @SessionAttributes 傳遞和保存數(shù)據(jù)@PathVariable
用于將請求URL中的模板變量映射到功能處理方法的參數(shù)上,即取出uri模板中的變量作為參數(shù)。
@requestParam
@requestParam主要用于在SpringMVC后臺控制層獲取參數(shù),類似一種是request.getParameter(“name”),它有三個常用參數(shù):defaultValue = “0”, required = false, value = “isApp”;defaultValue 表示設置默認值,required 銅過boolean設置是否是必須要傳入的參數(shù),value 值表示接受的傳入的參數(shù)類型。
@ResponseBody
該注解用于將Controller的方法返回的對象,通過適當?shù)腍ttpMessageConverter轉換為指定格式后,寫入到Response對象的body數(shù)據(jù)區(qū)。
@Component
相當于通用的注解,當不知道一些類歸到哪個層時使用,但是不建議。
@Repository
用于注解dao層,在daoImpl類上面注解。
-
什么是ioc,具體作用?
AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向對象編程(OOP)的一種補充,目前已成為一種比較成熟的編程方式。
在傳統(tǒng)的業(yè)務處理代碼中,通常都會進行事務處理、日志記錄等操作。雖然使用OOP可以通過組合或者繼承的方式來達到代碼的重用,但如果要實現(xiàn)某個功能(如日志記錄),同樣的代碼仍然會分散到各個方法中。這樣,如果想要關閉某個功能,或者對其進行修改,就必須要修改所有的相關方法。這不但增加了開發(fā)人員的工作量,而且提高了代碼的出錯率。
為了解決這一問題,AOP思想隨之產生。AOP采取橫向抽取機制,將分散在各個方法中的重復代碼提取出來,然后在程序編譯或運行時,再將這些提取出來的代碼應用到需要執(zhí)行的地方。這種采用橫向抽取機制的方式,采用傳統(tǒng)的OOP思想顯然是無法辦到的,因為OOP只能實現(xiàn)父子關系的縱向的重用。雖然AOP是一種新的編程思想,但卻不是OOP的替代品,它只是OOP的延伸和補充。
-
請說說你在項目中怎么使用AOP?具體干了什么?
AOP的使用,使開發(fā)人員在編寫業(yè)務邏輯時可以專心于核心業(yè)務,而不用過多的關注于其他業(yè)務邏輯的實現(xiàn),這不但提高了開發(fā)效率,而且增強了代碼的可維護性。
img -
通過新增操作怎么把數(shù)據(jù)存入到數(shù)據(jù)庫,把具體步驟列出來,在什么層干了什么?
controller:控制層
service:服務層
mapper:跟數(shù)據(jù)庫交互
pojo:實體類
-
數(shù)據(jù)庫怎么把行變成列?
關鍵的行轉列的函數(shù)pivot出場了,通過這個函數(shù)我們把分數(shù)填充到轉換的列語文、數(shù)學的列值。
img -
能說說后端你會什么框架嗎?
spring,springmvc,springboot,springcloud了解
-
前端到后端一整套流程是什么
pojo>mapper接口>service>controller>html
-
redis緩存你在這個項目是用來做什么的
Redis(REmote DIctionary Server) Redis是一個開源的使用ANSI C語言編寫、跨平臺、支持網絡、可基于內存亦可持久化的日志型、Key-Value非關系型數(shù)據(jù)庫,并提供多種語言的API。
Redis支持以下幾種類型數(shù)據(jù)的存儲:字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等類型。
【Redis 優(yōu)勢】
- 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
- 豐富的數(shù)據(jù)類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個操作是原子性的。多個操作也支持事務,即原子性,通過MULTI和EXEC指令包起來。
- 豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。
-
說說你對事務的理解,分布式事務是什么樣的?
數(shù)據(jù)庫中的事務是指對數(shù)據(jù)庫執(zhí)行一批操作,這些操作最終要么全部執(zhí)行成功,要么全部失敗,不會存在部分成功的情況。
分布式事務是單個事件導致兩個或多個不能以原子方式提交的單獨數(shù)據(jù)源的突變的情況。在微服務的世界中,它變得更加復雜,因為每個服務都是一個工作單元,并且在大多數(shù)情況下,多個服務必須協(xié)同工作才能使業(yè)務成功。
-
數(shù)據(jù)庫如何在表中刪除多個id的內容,有幾種方法
后臺方法
imgmybatis 根據(jù)多個id查詢數(shù)據(jù) foreach標簽
//根據(jù)主鍵ID刪除一條記錄 int deleteCategory(String[] categoryId); <!-- 根據(jù)主鍵刪除一條記錄 --> <delete id="deleteCategory"> delete from category where Category_ID in <foreach item="item" index="index" collection="array" open="(" separator="," close=")"> #{item} </foreach> </delete> -
查詢一萬條數(shù)據(jù)的一整套流程
如果數(shù)據(jù)量超過一萬條,采取循環(huán)查詢思路實例
-
從sql到contrller全寫出來
sql寫在mapper.xml
mapper接口>service>controller
-
項目中哪些地方用了事務,事務都有哪些
[圖片上傳失敗...(image-139e13-1646215318937)]
-
捕獲異常,異常有哪些,從哪來的
[圖片上傳失敗...(image-535032-1646215318937)]
-
mybatis的配置文件是哪個?包含哪些標簽/內容?
mybatis-config.xml文件
environments標簽
[圖片上傳失敗...(image-330305-1646215318937)]
①environments
這個很好理解,根據(jù)語義也就是配置環(huán)境,使用default屬性指定生效的環(huán)境
其中每個環(huán)境都有一個對應的id,比如:
②中的環(huán)境id為development,也就是開發(fā)環(huán)境。⑤中的環(huán)境id為test,也就是測試環(huán)境。③transactionManager
事務管理器,我們昨天執(zhí)行增刪改操作時,后面需要提交事務,這個也就是和其相對應。
④dataSource
數(shù)據(jù)源,type表示數(shù)據(jù)源的類型,此處是數(shù)據(jù)源連接池類型的。
其中這塊的內容,我們可以封裝到一個配置文件中: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=1alter table 表名 change 舊列名 新列名 類型(長度) 約束; -
在全國的身份證表中,我這里有一個身份證號,查詢是否重復,重復的有哪些?
數(shù)據(jù)是用集合存儲,按照不同的集合方法來進行查重
比如List,可以用contains()方法查詢集合中是否包含當前數(shù)據(jù)
-
解釋一下事務的原理?(不要講特性)
數(shù)據(jù)庫事務的隔離級別
討論MySQL的事務處理特性的實現(xiàn)原理之前我們需要先了解下MySQL對MVCC的支持,關于MVCC 維基百科有如下解釋。
多版本并發(fā)控制(Multiversion concurrency control, MCC 或 MVCC),是數(shù)據(jù)庫管理系統(tǒng)常用的一種并發(fā)控制,也用于程序設計語言實現(xiàn)事務內存。MVCC意圖解決讀寫鎖造成的多個、長時間的讀操作餓死寫操作問題。每個事務讀到的數(shù)據(jù)項都是一個歷史快照(snapshot)并依賴于實現(xiàn)的隔離級別。寫操作不覆蓋已有數(shù)據(jù)項,而是創(chuàng)建一個新的版本,直至所在操作提交時才變?yōu)榭梢???煺崭綦x使得事物看到它啟動時的數(shù)據(jù)狀態(tài)
-
根據(jù)事務四個特性(一致性,原子性,隔離性,持久性),一一舉個生活例子
1、原子性是指事務是一個不可再分割的工作單位,事務中的操作要么都發(fā)生,要么都不發(fā)生。
A給B轉帳100元錢
2、一致性是指在事務開始之前和事務結束以后,數(shù)據(jù)庫的完整性約束沒有被破壞。這是說數(shù)據(jù)庫事務不能破壞關系數(shù)據(jù)的完整性以及業(yè)務邏輯上的一致性。
對銀行轉帳事務,不管事務成功還是失敗,應該保證事務結束后ACCOUNT表中aaa和bbb的存款總額為2000元。
3、多個事務并發(fā)訪問時,事務之間是隔離的,一個事務不應該影響其它事務運行效果。
4、持久性,意味著在事務完成以后,該事務所對數(shù)據(jù)庫所作的更改便持久的保存在數(shù)據(jù)庫之中,并不會被回滾。
即使出現(xiàn)了任何事故比如斷電等,事務一旦提交,則持久化保存在數(shù)據(jù)庫中。
-
數(shù)據(jù)庫多表連接(內外連接)
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 可以省略
* 左外連接:以左表為驅動表,左邊是全數(shù)據(jù),右邊可能為空
* 右外連接:以右表為驅動表,右邊是全數(shù)據(jù),左邊可能為空
注意:還有 using, 但需字段名相同。 using(字段名)。
【多表查詢的子查詢】
一個SQL語句查詢的過程中需要依賴另一個查詢語句.
科創(chuàng)信息面試題(Java工程師)
基礎問答
1.用js實現(xiàn)隨機選取10–100之間的10個數(shù)字,存入一個數(shù)組,并排序。
<script type="text/javascript">
//首先創(chuàng)建一個空數(shù)組,用來放10個數(shù)字
var Array = [];
//接下來定義一個函數(shù),這個函數(shù)是寫10~100的隨機數(shù),我們現(xiàn)在把他封裝成一個函數(shù)
function getRandom(num1,num2){
var transition = num2 - num1 + 1;//這里面的加1是為了能夠取到100
var res = Math.floor(Math.random() * transition + num1);
return res;
}
//上面的代碼已經獲取了num1~num2的隨機數(shù)
//下面是遍歷出10個隨機數(shù),并把十個數(shù)用push放法放到新定義的數(shù)組里面
for(var i = 0; i < 10; i++){
Array.push(getRandom(10,100));
}
//最后用sort方法進行排序
Array.sort(function(a,b){
return a > b;
})
//打印數(shù)組Array
console.log(Array);
</script>
2.看下列代碼,將會輸出什么?
var foo = 1;
function test(){
console.log(foo);
var foo = 2;
console.log(foo);
}
test();
函數(shù)聲明與變量聲明會被JavaScript引擎隱式地提升到當前作用域的頂部,但是只提升名稱不會提升賦值部分。
解析:輸出undefined 和 2
本質:只提升聲明部分
3.寫一個function,清除字符串前后空格。(使用正則表達式,兼容所有)
function trim(str) {
if (str && typeof str === "string") {
return str.replace(/(^\s*)|(\s*)$/g,""); //去除前后空白符
}
}
4.將下面表格的奇數(shù)行、偶數(shù)行顏色分別設置為白色、紅色、懸浮為黃色
<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寫冒泡排序法的例子
“冒泡排序法”可以將一個無序的數(shù)組按照從小到大的順序或者是從大到小的順序進行排序,是一種較為常見的排序算法,因為數(shù)據(jù)從小到大或者從大到小地到數(shù)列頭或者數(shù)列末的過程稱為“冒泡”。對于冒泡排序我覺得最重要的兩點就是:(1)需要重新排序的次數(shù),即循環(huán)的次數(shù),這個是根據(jù)數(shù)組的序列的大小來定的,比如數(shù)組的大小為n的話,需要循環(huán)的次數(shù)就為(n - 1)次;(2)另外一個就是每次循環(huán)需要進行數(shù)據(jù)之間比較的次數(shù),每次排序后可以確定出最大或者最小的那個數(shù)據(jù),下次循環(huán)時就不用再進行比較了,所以每次進行比較的次數(shù)是(n - i);
對于一個數(shù)組無序的情況,無論是從大到小排序還是從小到大冒泡,假如是一個n個數(shù)據(jù)的數(shù)組,那么第一個數(shù)據(jù)無需跟自己進行大小比較了,那么需要進行比較的是跟余下的n - 1個數(shù)據(jù),所以需要重新進行排序的循環(huán)次數(shù)是n - 1次,在每次循環(huán)的過程中需要進行的比較次數(shù)的確定也是一個關鍵,在第一次循環(huán)的過程可以確定(以從小到大為例)最大的那個數(shù)那么在下一次的循環(huán)中就不用再進行比較了。
下面這個實例是對數(shù)組進行從小到大排序:
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] + " ");
}
}
}
輸出結果為:
初始數(shù)組為:63 4 24 1 3 15
排序后的數(shù)組為:1 3 4 15 24 63
7.Array和 ArrayList有何區(qū)別?
Array 可以存儲基本數(shù)據(jù)類型和對象,ArrayList 只能存儲對象。
Array 是指定固定大小的, ArrayList 是動態(tài)數(shù)組,長度動態(tài)可變,會自動擴容。不使用泛型的時候,可以添加不同類型元素。。
Array 內置方法沒有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
8.==與equlas有什么區(qū)別?
1.基本數(shù)據(jù)類型和引用數(shù)據(jù)類型==的比較作用效果是不同的
1)基本數(shù)據(jù)類型 = =比較的是值是相同
2)引用數(shù)據(jù)類型 = =比較的是引用的地址是都相同
2.equals()本質上還是= = 只是很多類重寫了equals()方法
equals()默認使用的是引用比較,只是很多類重寫了equals()讓其變成了值比較,所以通常情況下equals()是值比較
3.兩個對象的hashCode()相等 那么equals()一定為true嗎?
hashCode()相等不一定為true,因為在散列表中,hashCode() 相等即兩個鍵值對的哈希值相等,然而哈希值相等,并不一定能得出鍵值對相等。
數(shù)據(jù)庫類題目(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:教師名字
- 查詢所有同學的學號、姓名、選課數(shù)、總成績
#第一種
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 "課程成績高的學生的信息及課程分數(shù)
#第一種 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
拓維面試題(運維工程師、數(shù)據(jù)庫工程師)
基礎題
1.請簡述下數(shù)據(jù)庫設計的3范式。
第一范式的目標是確保每列的原子性:如果每列都是不可再分的最小數(shù)據(jù)單元(也稱為最小的原子 單元),則滿足第一范式(1NF)
第二范式首先滿足第一范式,并且表中非主鍵列不存在對主鍵的部分依賴。 第二范式要求每個表只描述一 件事情
第三范式定義是,滿足第二范式,并且表中的列不存在對非主鍵列的傳遞依賴。除了主鍵訂單編 號外,顧客姓名依賴于非主鍵顧客編號
2.簡述Oracle中DML、DDL、DCL的使用。
- dml 數(shù)據(jù)操縱語言,如 select、update、delete、insert
- ddl 數(shù)據(jù)定義語言,如 create table 、drop table
- dcl 數(shù)據(jù)控制語言,如 commit、rollback、grant、invoke
3.請列舉下SQL語句中有哪些聚合函數(shù)?
AVG 返回指定組中的平均值,空值被忽略
COUNT 返回指定組中項目的數(shù)量
MAX 返回指定數(shù)據(jù)的最大值
MIN 返回指定數(shù)據(jù)的最小值
SUM 返回指定數(shù)據(jù)的和,只能用于數(shù)字列,空值被忽略
4.請列舉多表關聯(lián)查詢的方式,關鍵字分別是什么?
內鏈接(INNER JOIN)
外鏈接
左外連接( LEFT[OUTER]JOIN)
右外連接(RIGHT[OUTER]JOIN)
全外鏈接(FULL[OUTER]JOIN)
交叉連接/笛卡爾積(CROSS JOIN)
5.Oracle存儲過程包含哪三部分,并寫出程序過程的語法。
過程聲明,執(zhí)行過程部分,存儲過程異常
無參程序過程語法
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實操題
數(shù)據(jù)結構和模擬數(shù)據(jù)如下表所示:
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.請創(chuàng)建課程表C,并插入數(shù)據(jù),寫出具體的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.查詢選修了課程的學員人數(shù)。
#第一種
SELECT COUNT(*)
FROM S
WHERE EXISTS( SELECT * FROM SC WHERE SC.SNO = S.SNO )
#第二種
SELECT COUNT(DISTINCT SNO) FROM SC
3.查詢最低分數(shù)大于60分,最高分數(shù)小于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.查詢選修某課程的同學人數(shù)多于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
