某某面试题(1)
一, 选择题
-
下列关于栈的描述错误的是(B)
A. 栈是先进后出的线性表
B. 栈只能顺序存储
C. 栈具有记忆功能
D. 对栈的插入和删除操作中,不需要改变栈底指针
首先, 栈是允许在同一端进行插入和删除操作的特殊的线性表, 是一种数据结构的称呼
线性结构有两种不同的存储结构, 顺序存储结构和链式存储结构
所以, 只要符合在同一端进行插入和删除操作的特殊的线性表, 我们统称为栈
-
对于长度为 n 的线性表,在最坏的情况下,下列个排序法所对应的比较次数中正确的是(D)
A. 冒泡排序为n/2
B. 冒泡排序为n
C. 快速排序为n
D. 快速排序为n(n-1)/2
本题主要考查对排序算法的理解。冒泡排序法首先将第一个记录的关键字与第二个记录的关键字进行比较,若逆序则交换,然后比较第二个与第三个,以此类推,直至第n-1个与第n个记录的关键字进行比较。第一趟冒泡排序使最大的关键字元素放到最后。以此类推,进行第2~n次冒泡排序。如果在排序过程中不存在逆序,则排序结束。在最坏情况下,冒泡排序中,若初始序列为“逆序”序列,需要比较n(n-1)/2次。快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字比另一部分记录的关键字小,然后分别对这两部分记录继续进行排序,最终达到整个记录有序。对于快速排序,若初始记录序列按关键字有序或基本有序时,快速排序退化冒泡排序,最坏情况下比较次数为n(n-1)/2。
-
阅读下列代码后, 下列正确的说法是(A)
public class Person{ int arr[] = new int[10]; public static void main(String args[ ]){ System.out.println(arr[1]); } }
A 编译时将产生错误
B 编译时正确,运行时将产生错误
C 输出空
D 输出0
arr没有被static修饰, 所以说main方法无法访问到
-
执行以下程序后输出的结果是(D)
public class Test { public static void main(String[] args) { StringBuffer a = new StringBuffer("A"); StringBuffer b = new StringBuffer("B"); operator(a,b); System.out.println(a+","+b); } public static void operator(StringBuffer x,StringBuffer y){ x.append(y); y=x; } }
A. A,A
B. A,B
C. B,B
D. AB,B
public class Test {
public static void main(String args[]) {
//a和b都是引用,分别引用了new在堆中的两个StringBuffer对象。
StringBuffer a = new StringBuffer(“A”);
StringBuffer b = new StringBuffer(“B”);
Operator(a, b);
System.out.println(a + " " + b);
}public static void Operator(StringBuffer x, StringBuffer y) {
//由于main中调用Operator传入
//x和main中a引用了同一个在堆中的StringBuffer对象
//y和main中b引用了同一个在堆中的StringBuffer对象
x.append(y);//由于调用了append的作用,堆中的对象被改变。由"A",变"AB"
y = x;//由于=只是让y引用x引用的对象,此时x,y,a引用同一个"AB",b引用另一个"A"
} -
下列不属于持久化的是(A)
A. 把对象转换成为字符串的形式通过网络传输,在另一端接收到字符串把对象还原出来
B. 把程序数据从数据库中读出来
C. 从XML配置文件中读取程序的配置信息
D. 把程序数据保存为文件
百度百科:
什么是持久化: 持久化是将程序数据在持久状态和瞬时状态间转换的机制. 通俗的讲, 就是顺势数据(比如内存中的数据, 是不能永久保存的) 持久化为持久数据(比如持久化之数据库中, 能够长久保存)
数据持久化:
数据持久化就是将内存中的数据模型转换为存储模型, 以及将存储模型转换成为内存中的数据模型的统称. 数据模型可以是任何数据结构或对象模型, 存储模型可以是关系模型, xml, 二进制流等.
-
下列代码输出的结果是(B)
int x= 0; int y=10; do{ y--; ++x; }while(x<5); System.out.println(x+","+y);
A. 5,6
B. 5,5
C. 6,5
D. 6,6
-
下列程序段的输出结果是:( B )
void complicatedexpression_r(){ int x = 20,y=30; boolean j; j=x>50&&y>60||x>50&&y<-60||x<-50&&y>60||x<-50&&y<-60; System.out.println(j); }
A. true
B. false
C. 1
D. 011
此题考查运算符优先级。
题中符号的优先级排序是:’>’,’<’,’&&’,’||’。
即 b=(x>50&&y>60)||(x>50&&y<-60)||(x<-50&&y>60)||(x<-50&&y<-60);
x>50结果为false,x<-50结果为false,所以括号中的表达式结果都为false,四个false或的结果为false。
b为boolean类型,所以输出为false。 -
一个栈的输入序列为 123,则下列序列中不可能是栈输出的序列的是(C)
A. 2 3 1
B. 3 2 1
C. 3 1 2
D. 1 2 3
1进栈,1出栈,2进栈,2出栈,3进栈,3出栈,所以是123
1进栈,2进栈,2出栈,1出栈,3进栈,3出栈,所以是213
1进栈,2进栈,2出栈,3进栈,3出栈,1出栈,所以是231
1进栈,2进栈,3进栈,3出栈,2出栈,1出栈,所以是321
输入序列是123的输出序列就这4中情况;所以是C! -
当n = 5时, 下列函数的返回值是(D)
int foo(int n){ if(n<2) return n; return foo(n-1)+foo(n-2); }
A. 1
B. 8
C. 7
D. 5
解题思路如下:
当n=0时 f(0)=0
当n=1时 f(1)=1
当n=2时 f(2)=f(1)+f(0)=0+1=1
当n=3时 f(3)=f(2)+f(1)=0+1=2
当n=4时 f(4)=f(3)+f(2)=1+2=3
当n=5时 f(5)=f(4)+f(3)=3+2=5 -
设一个二维数组A[m][n], 假设A[0][0]存放位置在644(10). A[2][2]存放的位置在676(10), 每个元素占一个空间, 问A[3][3](10)存放在什么位置?脚注(10)表示用10进制表示( C )
A. 688
B. 678
C. 692
D. 699
解法一: 只看对角线元素 ,A[0][0]和a[1][1]间隔距离设为x, 那么A[0][0]和A[2][2] 间隔就为2x, 按照比例计算x为(676-644)/2=16, 所以说A[3][3] 的位置为644+16*3=692
解法二: 对于arr[m][n]而言:
arr[i][j]的地址为:arr + i*n + j
arr[0][0]的地址为644
所以,由A[2][2]可得:644 + n*2 + 2 = 676,得n=15 (每行15个元素)
所以A[3][3]的地址为:644+15*3 + 3 = 692
二, 简答题
-
解释以下什么是Servlet; 说一说Servlet的生命周期
Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。 它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTTP服务器上的数据库或应用程序)的中间层。
Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机Servlet生命周期可以分成四个阶段:加载和实例化、初始化、服务、销毁。
当客户第一次请求时,首先判断是否存在 Servlet 对象,若不存在,则由 Web 容器创建对象,而后调用 init()方法对其初始化,此初始化方法在整个Servlet生命周期中只调用一次。
完成Servlet对象的创建和实例化之后,Web容器会调用Servlet对象的service()方法来处理请求。
当Web容器关闭或者Servlet对象要从容器中被删除时,会自动调用destory()方法。
-
过滤器有哪些作用和用法?
对于一个 web 应用程序来说,过滤器是处于 web 容器内的一个组件,它会过滤特定请求资源请求信息和响应信息。一个请求来到时,web 容器会判断是否有过滤器与该信息资源相关联,如果有则交给过滤器处理,然后再交给目标资源,响应的时候则以相反的顺序交给过滤器处理,最后再返回给用户浏览器。
常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请求或响应进行加解密处理、触发资源访问事件等。
-
写出冒泡排序的实现
import java.util.Arrays; public class Test { public static void main(String[] args) { int[] randomArray = getRandomArray(10); System.out.println(Arrays.toString(randomArray)); quickSort(randomArray, 0, randomArray.length - 1); System.out.println(Arrays.toString(randomArray)); } /** * 快速排序 * * @param arr 需要排序的数组 * @param leftBound 左边界 左边第一个元素的索引 * @param rightBound 右边界 右边第一个元素的索引 */ public static void quickSort(int[] arr, int leftBound, int rightBound) { //避免左右边界相交越界,定义递归算法的递归尾 if (leftBound > rightBound) { return; } //左浮标,定义数组做左侧的元素索引 int lDrogue = leftBound; //右浮标,定义数组最右侧的元素索引 int rDrogue = rightBound; //将数组最左侧的原则作为基准数 int pivot = arr[lDrogue]; //当两个浮标索引不相等的情况下,持续移动 while (lDrogue != rDrogue) { //右漂浮左移 while (lDrogue < rDrogue && arr[rDrogue] >= pivot) { rDrogue--; } //左浮标右移 while (lDrogue < rDrogue && arr[lDrogue] <= pivot) { lDrogue++; } //当做到这里的时候说明,左漂浮和右漂浮上的数据已经不满足条件 //这里的条件就是左漂浮对应的值大于基准值, 右漂浮对应的值小于基准值 //开始将不符合条件的元素进行交换 swap(arr, lDrogue, rDrogue); } //走到这里说明两个漂浮发生了重合,漂浮所在的位置也就是基准值应该放的位置 swap(arr, leftBound, lDrogue); quickSort(arr, leftBound, lDrogue - 1); quickSort(arr, lDrogue + 1, rightBound); } /** * 定义方法用于交换数组中的两个元素 * * @param arr 数组 * @param a 元素索引 * @param b 元素索引 */ public static void swap(int arr[], int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /** * 获得随机的数组 * * @param length 生成随机数组的长度 * @return */ public static int[] getRandomArray(int length) { int[] arr = new int[length]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) (Math.random() * 10000 + 1); } return arr; } }
-
写出一个单例的实现 ( 懒加载方式)
public class SingletonDemo { //私有化属性,持有自己的属性,static修饰,便于对外提供的方法执行创建对象的操作 private static SingletonDemo singletonDemo; //私有化构造器 private SingletonDemo() { } //对外提供方法获取对象,线程安全 public static synchronized SingletonDemo getInstance() { if (singletonDemo == null) { singletonDemo = new SingletonDemo(); return singletonDemo; } return singletonDemo; } }
三, SQL
Students学生表
sid | number | 学号 |
---|---|---|
sname | varchar2 (50) | 学生姓名 |
sage | number | 年龄 |
ssex | varchar2 (2) | 性别 |
Course课程表
cid | number | 课程编号 |
---|---|---|
cname | varchar2 (50) | 课程名称 |
tid | number | 教师编号 |
SC成绩表
sid | number | 学号 |
---|---|---|
cid | number | 课程编号 |
score | number | 成绩 |
-
查询姓 “张” 的学生名单 (至少两种方法以上)
select sname from student where sname like '张%'; SELECT * from people where name like '张__' or name like '张_';
-
查询男生, 女生人数各多少, 且男生年龄大于19岁, 女生年龄小于20岁
select * from (select count(1) as man from student where gender='男' and sage>19) as A , (select count(1) as feman from student where gender='女' and sage<20) as B
-
检索 “004” 课程分数小于60, 按照分数降序排列的同学学号
select sid from sc where score< 60 and cid = 4 order by score desc;
-
检索至少选修两门课程的学生学号 (至少两种方法以上)
select sid from sc group by sid having count(sid) > 1; select sid from sc group by sid where count(sid) > 1;
-
查询所选课程的成绩 (学生可能选择 1 门或多门课程) 都在70分以上的学生姓名, 课程名称和分数
SELECT student.sname,course.cname, sc.score FROM sc, course, student WHERE sc.score >70 AND sc.sid = student.sid AND sc.cid = sc.cid
-
删除 “002” 同学的 "001"课程的成绩
delete from sc where cid = 1 and sid = 2
-
当成绩表的数据量达到千万级别后, 请列举多种数据优化方式或者思路 (附加题)
附加题参考链接: https://mp.weixin.qq.com/s/OZkdf6Wk5W3HNzzH0qMDlA
四, 概念题
-
dubbo事务是如何处理的?????
分布式事务(事务补偿机制)
事务补偿即在事务链中的任何一个正向事物的操作,都必须存在一个完全符合回滚规则的可逆事务.
如果是一个完整的事务链, 则必须事物链中的每一个业务服务或操作都有对应的可逆服务. 如果按照上面的方式我们需要编写大量的代码来处理以保证事务的完整性, 我们可以考虑实现一个通用的事务管理器, 实现事务链和事务上下文的管理. 对于事务链上的任何一个服务正向和逆向操作均在事务管理和协同器(zookeeper)上注册
-
solr的增量是如何做到的????
solr有全量导入数据和增量导入数据两种方式, 在数据量较大的时候, 频繁的更新索引会消耗系统的性能, 但是如果更新效率较低, 则会影响数据的准确性, 在这种情况下, 更新时间的间隔是个很难界定的问题.
增量索引解决了这个问题, 我们可以在较短的时间内只更新那些变化的数据, 这样就避免了大批量的数据更新, 因为数据量的小, 因此我们可以设置较短的时间间隔, 以此来提升用户的体验度.
1️⃣ 配置数据源
增量索引的关键是找到那些修改的数据. 所以我们要在数据库表上添加一个标识符 (比如updateTime), 数据类型是时间戳(timestamp)
solr本身提供了一个last_index_time, 这个字段记录每条记录的导入时间(包括增量导入和全量导入) ,我们只需要将updateTime和last_index_time比较即可得到上一次索引更新以后的变化记录
2️⃣ 配置data-config.xml文件
全量索引继续保留, 所以原来的配置不需要更改, 我们只需要添加增量索引的配置. 首先, 我们在索引中用到了updateTime字段, 所以需要添加updateTime; 其次增量索引的关键就是找到更新的那些数据, 我们要使用last_index_time字段更新代码如下
deltaQuery="select id from product where updateTime > '${dataimporter.last_index_time}'"
我们根据上述获得的id更新索引
deltaImportQuery="select * from product where id='${dih.delta.id}'"
最终配置:
<dataConfig> <dataSource name="jfinal_demo" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.51.71:3306/demo" user="root" password="123456" batchSize="-1" /> <document name="testDoc"> <entity name="blog" dataSource="jfinal_demo" pk="id" query="select * from product" deltaImportQuery="select * from product where id='${dih.delta.id}'" deltaQuery="select id from product where updateTime > '${dataimporter.last_index_time}'"> <field column="id" name="id"/> <field column="name" name="name"/> <field column="price" name="price"/> <field column="updateTime" name="updateTime"/> </entity> </document> </dataConfig>
3️⃣ 配置schema.xml
<field name="id" type="text_ik" indexed="true" stored="true" /> <field name="name" type="text_ik" indexed="true" stored="true" /> <field name="price" type="text_ik" indexed="true" stored="true" /> <field name="updateTime" type="text_ik" indexed="true" stored="true" />
参考链接 :https://blog.csdn.net/u010942465/article/details/51347923
-
如果solr中导入了错误的值或者空值, 我们如何获取这些错误条件的搜索结果?✨
正常情况下我们都是按有值的方式去搜索,但是有时候有一些字段为null,solr中就没有存储进去,我们怎么获取这个字段不存在为条件的搜索结果了,我们只需要在搜索字段前加上负号
参考链接:
- https://blog.csdn.net/weixin_34195364/article/details/86008270
- https://blog.csdn.net/jiangchao858/article/details/76407937
-
sql索引的优缺点????
优点:
大大提高系统的性能
-
通过创建唯一性索引, 可以保证数据库表中每一行数据的唯一性
-
可以大大加快数据的检索速度, 这也是创建索引的最主要的原因
-
可以加速表与表之间的联系, 特别是在实现数据库的参考完整性方面特别有意义
参考完整性要求关系中不允许引用不存在的实体. 与实体完整性是关系模型必须满足的完整性约束条件, 目的是保证数据的一致性. 参照完整性又称为引用完整性
-
在使用分组和排序子句进行数据检索时, 同样可以显著减少查询中排序的时间
-
通过使用索引, 可以在查询过程中, 使用优化隐藏器, 提高系统的性能
sql的优化隐藏器: https://zhidao.baidu.com/question/39271452.html
缺点:
- 创建索引和维护索引要耗费时间, 这种时间的耗费随着时间的增加而增加
- 索引需要占用物理空间, 除了数据库表占数据空间之外, 每一个所索引还要占用一定的物理空间
- 当对表中的数据进行增加, 删除和修改的时候, 索引也要动态的维护, 这样就降低了数据的维护速度
参考链接: https://blog.csdn.net/az03100110/article/details/78788980
-
-
事务传播的特性, 如果a() 调用了b()方法b()抛异常了, 如何确保a()不回滚????
这里主要考察的是事务的7种传播特性
@Transactional(propagation=Propagation.REQUIRED)
序号 传播行为 含义 1 REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 2 SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行 3 MANDATORY 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行 4 NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行 5 NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常 6 REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个已经存在的事务挂起 7 NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务 事务在a()种调用了b()方法的传播案例
b()的事务配置 a()没有事务的结果 a()有事务的结果 REQUIRED b()创建自己的事务 b()接受a()的事务 SUPPORTS b()不创建自己的事务 b()接受a()的事务 MANDATORY b()报异常 b()接受a()的事务 NESTED b()创建自己的事务 b()接受a()的事务,成为a()嵌套的子事务 NEVER b()不创建自己的事务 b()报异常 REQUIRES_NEW b()创建自己的事务 b()不接受a()的事务,b()先执行,内层事务失败不会影响外层事务 NOT_SUPPORTED b()不创建自己的事务 b()不接受a()的事务,b()先执行 声明式事务是基于Spring AOP实现的, 将具体的业务逻辑和事务处理解耦, 在SpringAOP的代理下, 只有目标方法由外部调用, 目标方法才由Spring生成的代理对象来管理, 否则会造成子调用的问题.
注意: 同一个类中a()方法没有@Transactional注解, 在其内部调用@Transactional 注解的方法,有@Transactional 注解的方法b()的事务被忽略,不会发生回滚。
参考链接:
- https://blog.csdn.net/u010235716/article/details/90171802
- https://blog.csdn.net/qq_37221991/article/details/90409001
- https://blog.csdn.net/qq_30336433/article/details/83338835
-
manven的jar包冲突如何解决????
参考右边的 Maven Projects,找到 Dependencies 选项展开后即可查看项目的依赖树。进行分析
参考链接:
- https://blog.csdn.net/qq_33349750/article/details/75452706
- https://blog.csdn.net/noaman_wgs/article/details/81137893
- https://blog.csdn.net/SmileorSilence/article/details/79065284
-
dubbo都有哪些协议, 讲一下zookeeper????
dubbo有九种协议,但是Dubbo官网是推荐我们使用Dubbo协议的
1️⃣dubbo 协议(默认)
连接个数:单连接 连接方式:长连接 传输协议:TCP 传输方式:NIO异步传输 序列化:Hessian 二进制序列化 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压 满提供者,尽量不要用dubbo协议传输大文件或超大字符串。 适用场景:常规远程服务方法调用
2️⃣rmi 协议
连接个数:多连接 连接方式:短连接 传输协议:TCP 传输方式:同步传输 序列化:Java标准二进制序列化 适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。 适用场景:常规远程服务方法调用,与原生RMI服务互操作
3️⃣hessian 协议
连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:Hessian二进制序列化 适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。 适用场景:页面传输,文件传输,或与原生hessian服务互操作
4️⃣http 协议
连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:表单序列化 ,即 json 适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。 适用场景:需同时给应用程序和浏览器JS使用的服务。
5️⃣webservice 协议
连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:SOAP文本序列化 适用场景:系统集成,跨语言调用
6️⃣thrift 协议
当前 dubbo 支持的 thrift 协议是对 thrift 原生协议的扩展,在原生协议的基础上添加了一些额外的头信息,比如 service name,magic number 等。 使用 dubbo thrift 协议同样需要使用 thrift 的 idl compiler 编译生成相应的 java 代码,后续版本中会在这方面做一些增强。
7️⃣memcached 协议
基于 memcached实现的 RPC 协议。
8️⃣redis 协议
基于 Redis实现的 RPC 协议。
9️⃣rest (RestFull协议)
基于标准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的简写)实现的REST调用支持
参考链接:
- https://blog.csdn.net/xiaojin21cen/article/details/79834222
- http://dubbo.apache.org/zh-cn/docs/user/references/protocol/rest.html
zookeeper: 是一款分布式管理软件,常常用它作为注册中心, (依赖zookeeper的发布订阅功能) , 配置文件中心, 分布式锁, 集群管理等.
-
webservice技术????
Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。
简单的说,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然。跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。 远程调用,就是一台计算机的应用可以调用其他计算机上的应用。例如:支付宝,支付宝并没有银行卡等数据,它只是去调用银行提供的接口来获得数据。还有天气预报等,也是气象局把自己的系统服务以webservice服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能。
参考链接:
- https://blog.csdn.net/c99463904/article/details/76018436
- https://blog.csdn.net/xiaojin21cen/article/details/79834222
-
mysql的优化代码级别, 还有分库和分表如何分????
参考文献:
- https://www.cnblogs.com/lonnie/p/10681512.html
- https://blog.csdn.net/qq_33936481/article/details/73691331
-
hibernate 以及mybatis(更加灵活)的异同, 以及应用场景????
????Mybatis的技术特点:
- 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
- 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
- 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
- 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
- 需要编写结果映射。
???? Mybatis应用场景:
需求多变的互联网项目,例如电商项目。
????Hibernate技术特点:
- 标准的orm框架,程序员不需要编写SQL语句。
- 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
- 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
- 程序员不能自主的去进行SQL性能优化。
????Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等。
上一篇: 浅谈Java中的克隆close()和赋值引用的区别
下一篇: 20200724:力扣197周周赛上