数据持久化⾯试题
1. ORM框架的原理是什么?
ORM是对象-关系映射(Object-Relational Mapping,简称ORM)
它是java中持久层框架技术的⼀种实现思想,基于这种思想常见的框架有MyBatis、Hibernate等。其原理是建⽴java中类(实体类)和数据表之间的映射关系,然后通过反射的思想,动态获取类中的属性,此时属性对应了表中的列,所以能够动态产⽣JDBC代码从⽽达到操作数据库的⽬的。
2. 什么是DAO模式?
dao全称是data access object,数据库访问对象,主要的功能就是⽤于进⾏数据操作的,在程序的标准开发架构中属于数据层的操作
DAO组成
在整个DAO中实际上都是以接⼝为操作标准的,即:客户端依靠DAO实现的接⼝进⾏操作,⽽服务端要将接⼝进⾏具体的实现。DAO由以下⼏个部分组成。
1.DatabaseConnection:专门负责数据库的打开与关闭操作的类
2.VO:主要由属性、setter、getter⽅法组成,VO类中的属性与表中的字段相对应,每⼀个VO类的对象都表⽰表中的每⼀条记录;
3.DAO:主要定义操作的接⼝,定义⼀系列数据库的原⼦性操作,例如:增加、修改、删除、按ID查询等;
4.Impl : DAO接⼝的真实实现类,完成具体的数据库操作,但是不负责数据库的打开和关闭;
5 Proxy :代理实现类,主要完成数据库的打开和关闭,并且调⽤真实实现类对象的操作
6 Factory :⼯⼚类,通过⼯⼚类取得⼀个DAO的实例化对象
3. 举⼀个多对多关联的例⼦,并说明如何实现多对多关联映射。
例如:商品和订单、学⽣和课程都是典型的多对多关系。⾸先在数据库表中需要通过第三张关系表来进⾏数据的维护,该关系表中主要包含了两个外键。具体代码中实现根据框架的不同也有不同的实现⽅式,⽐如JPA中可以在实体类上通过@ManyToMany注解配置多对多关联或者通过映射⽂件中的和标签配置多对多关联,但是实际项⽬开发中,很多时候都是将多对多关联映射转换成两个多对⼀关联映射来实现的。
4. 谈⼀下你对继承映射的理解。
继承关系的映射策略有三种:
①每个继承结构⼀张表(table per class hierarchy),不管多少个⼦类都⽤⼀张表。
②每个⼦类⼀张表(table per subclass),公共信息放⼀张表,特有信息放单独的表。
③每个具体类⼀张表(table per concrete class),有多少个⼦类就有多少张表。
第⼀种⽅式属于单表策略,其优点在于查询⼦类对象的时候⽆需表连接,查询速度快,适合多态查询;缺点是可能导致表很⼤。后两种⽅式属于多表策略,其优点在于数据存储紧凑,其缺点是需要进⾏连接查询,不适合多态查询。
5. 什么是Hibernate,好处是什么?
1、Hibernate是⼀个基于ORM思想的操作数据库的框架技术,实现了对JDBC的封装;
2、Hibernate⽤的是⾯向对象的⽅法,但是在关系型数据库⾥,存的是⼀条条的记录;为了⽤纯⾯向对象的思想解决问题,所以需要将程序中的对象和数据库中的记录建⽴起映射关系,ORM就是将对象和数据库中的记录建⽴起映射的技术;
3、Hibernate通过⽅⾔来⾃动切换不同的数据库,⽆需在代码中编写;
4、使⽤Hibernate的基本流程是:配置Configuration对象、产⽣SessionFactory、创建session对象,启动事务,完成CRUD操作,提交事务,关闭session;
5、使⽤Hibernate时,先要配置l⽂件,其中配置数据库连接信息和⽅⾔等,还要为每个实体配置相应的l⽂件,l⽂件中需要登记每个l⽂件。
6. Hibernate的核⼼思想?
Hibernate是⼀个采⽤ORM(Object/Relation Mapping对象关系映射)机制持久层的开源框架其主要核⼼思想是⾯向对象,⽽⾮⾯向过程,⽽这个⾯向对象则主要通过ORM实现。
7. 什么是Mybatis?
MyBatis 是⼀款优秀的持久层框架,它⽀持定制化 SQL、存储过程以及⾼级映射。MyBatis 避免了⼏乎所有的 JDBC 代码和⼿动设置参数以及获取结果集。My Batis 可以使⽤简单的 XML 或注解来配置和映射原⽣信息,将接⼝和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
8. MyBatis中使⽤#和$书写占位符有什么区别?
1.#将传⼊的数据都当成⼀个字符串,会对⾃动传⼊的数据加⼀个双引号。
tap up2.$将传⼊的数据直接显⽰⽣成在sql中。
3.#⽅式能够很⼤程度防⽌sql注⼊。
4.$⽅式⽆法防⽌Sql注⼊。
5.$⽅式⼀般⽤于传⼊数据库对象
6.⼀般能⽤#的就别⽤$
注意: ⼀般如果将表名、列名作为参数的动态功能操作时,必须使⽤$,⽽不能使⽤#。如MyBatis排序时使⽤order by 动态参数时需要使⽤$。
9. Hibernate 与 Mybatis区别(MyBatis与Hibernate有什么不同)。
相同点:
都是基于ORM思想的java持久层框架技术,都封装了JDBC实现数据库操作,提⾼了开发数据库编码的效率。
不同点:
1) Hibernate是⼀个全⾃动的orm映射⼯具,它可以⾃动⽣成sql语句;MyBatis需要我们⾃⼰在xml配置⽂件中写sql语句。因为hibernate⾃动⽣成sql语句,我们⽆法控制该语句,我们就⽆法去写特定的⾼效率的sql。对于⼀些不太复杂的sql查询,hibernate可以很好帮我们完成,但是,对于特别复杂的查询,hibernat e就很难适应了,这时候⽤MyBatis就是不错的选择,因为MyBatis还是由我们⾃⼰写sql语句;
2) Mybatis⽐hibernate对存储过程的⽀持更好⼀些。
10. 持久层设计要考虑的问题有哪些?
所谓"持久"就是将数据保存到存储设备中以便今后使⽤,简单的说,就是将内存中的数据保存到关系型数据库、⽂件系统、消息队列等提供持久化⽀持的设备中。持久层就是系统中专注于实现数据持久化的相对独⽴的层⾯。
持久层设计的⽬标包括: - 数据存储逻辑的分离,提供抽象化的数据访问接⼝。
- 数据访问底层实现的分离,可以在不修改代码的情况下切换底层实现。
- 资源管理和调度的分离,在数据访问层实现统⼀的资源调度(如缓存机制)。
- 数据抽象,提供更⾯向对象的数据操作。
11. 你⽤过的持久层框架有哪些
持久层主要是负责将数据进⾏持久化,早期的JDBC代码太⿇烦繁琐,所以出现了⼀系列基于ORM思想的持久层框架,我主要使⽤的是MyBatis框架,其他的⽐如Hibernate以及JPA有⼀些了解。
技巧:选⾃⼰最熟的持久化框架,说明其关键特点
12. @OneToMany注解的mappedBy属性有什么作⽤?
技巧:mappedBy 属性的主要作⽤是告诉hibernate关联关系是通过对⽅外键引⽤完成关联映射,这⼀点必须说清楚。One的⼀⽅会成为主控⽅,加⼊mappedBy 以后,就不会⽣成这两张关联表的中间表了,⽽是在Many的⼀⽅的表中⽣成⼀列作为外键。
linux移植有哪些步骤13. MyBatis中的动态SQL是什么意思?
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们⽅便的在SQL语句中实现某些逻辑,⼀般在我们的l映射⽂件中使⽤,MyBatis中⽤于实现动态SQL的标签元素主要有:
if
choose(when,otherwise)
trim
where
set
foreach
14. 如何解决 Mybatis “n+1”问题。configure英文
N+1问题主要是数据库表中的级联问题,就是在查询的时候使⽤了association或collection标签进⾏关联数据时,如果使⽤了嵌套的select⽅式,则会造成N+1的问题,解决⽅案是:
第⼀种⽅法是使⽤⼀条多表关联的SQL语句,⼀次性查询出需要的数据。
第⼆种⽅法是使⽤MyBatis的延迟加载机制,在具体使⽤到的时候再去加载数据。
15. Mybatis 动态SQL相关标签作⽤及含义?
1.MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们⽅便的在SQL语句中实现某些逻辑。
2.MyBatis中⽤于实现动态SQL的元素主要有ifchoose(when,otherwise)trimwheresetforeach可以看出MyBatis的动态SQL的标签元素和接近JSP中的JSTL语法,下⾯我就分别详细的介绍⼀下
3.动态SQL中if的⽤法
4.动态SQL中choose⽤法
5.动态SQL中where语句的作⽤主要是简化SQL语句中where中的条件判断的注意: where元素的作⽤是给SQL语句添加⼀个条件判断. 如果输出后是and 开头的,MyBatis会把第⼀个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上
6.动态SQL中set元素主要是⽤在更新操作的时候,它的主要功能和where元素其实是差不多的
7.动态SQL中foreach主要⽤在构建in条件中,它可以在SQL语句中进⾏迭代⼀个集合。foreach元素的属性主要有item,index,collection,open,separator,close
8.动态SQL中trim语句
16. 什么是JDBC,简述实现⽅法?
JDBC是java进⾏数据库操作时的技术统称,提供了很多操作接⼝,但是编写的代码⾮常繁琐⿇烦,创建⼀个以JDBC连接数据库的程序,包含7个步骤:
1、加载JDBC驱动程序: Class.forName(“sql.jdbc.Driver”)
2、提供JDBC连接的URL: “jdbc:mysql://localhost:3306/数据库名”
3、创建数据库的连接 Connection conn = Connection(“URL”,”root”,”123456”)
4、创建⼀个执⾏sql命令的Statement对象 PreparedStatement pstmt = conn.prepareStatement(sql);
5、执⾏SQL语句 1)增删改 uteUpdate() à返回int为影响的⾏数2)查询 uteQuery()à返回ResultSet为查询的结果集
6、循环读取结果: ())
7、关闭JDBC相关资源对象
17. 请介绍⼀下数据库连接池技术?
1)数据库连接池技术主要是提⾼应⽤程序和数据库交互时的性能问题,因为连接数据库是⾮常耗费资源的,如果每个操作都去频繁连接和断开,则会造成巨⼤的开销,连接池技术即在系统初始化时,就创建⼀系列的连接对象放⼊集合中管理,需要连接数据库时从连接池中取出使⽤,使⽤完毕归还给连接池,这样的⽬的是提⾼同⼀个连接的可重⽤性。
2)java中有很多连接池框架,⽐如dbcp、c3p0,我个⼈⽐较喜欢使⽤阿⾥的druid连接池,因为性能稳定,功能强⼤。注:⼀般项⽬使⽤时直接添加maven引⽤
18. MySQL、Oracle、SQL Server各数据库服务的默认端⼝号?
1、MySQL:3306
2、Oracle:1521
3、SQL Server:14331
19. MyBatis中如何实现分页?
分页的⽬的是减少⼀次性查询出数据的额外开销,提⾼应⽤的性能。Mybatis中可以使⽤如下⼏种⽅案:
1、 sql语句分页,利⽤传递的页码和每页显⽰数,使⽤limit分页
2、采⽤mybatis插件实现分页
20. MyBatis中如何实现数据映射?
Mybatis要求我们⾃⼰完成查询sql语句,然后对查询的类进⾏映射,默认情况下如果类和实体属性⼀致,则可以直接使⽤reusltType进⾏关联映射,如果不⼀致,则需要⾃定义resultMap进⾏映射说明。当然如果数据库列是下划线,⽽java中是驼峰命名,则可以在mybatis主配置中添加驼峰命名的全局setting配置即可。
21. MyBatis中的缓存如何使⽤?
1)缓存是为了提⾼程序的性能,把从数据库中查询出来和使⽤过的对象保存在内存中,当以后要使⽤某个对象时,先查询缓存中是否有这个对象,如果有则使⽤缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使⽤。
2) Mybatis中有⼀级缓存和⼆级缓存,其中⼀级缓存是SqlSession级别的缓存,在同⼀个SqlSession操作时都会默认使⽤,当会话关闭则会⾃动清空⽆法使⽤。⼆级缓存是Mapper级别的缓存,需要在主配置中声明开启,然后在l中使⽤<cache>标签声明后才能使⽤。
3)缓存使⽤时需要注意,经常修改和准确度要求很⾼的数据不适合放⼊缓存中,因为很容易产⽣脏数据,从⽽造成程序中的数据不准确。
22. MyBatis中的使⽤流程?
1)⾸先项⽬中加⼊mybatis的依赖,如maven的l中添加
2)创建并修改l核⼼配置⽂件(配置全局属性、别名、数据库连接、注册的Mapepr等)
3)创建实体类和数据表映射
4)创建功能操作接⼝,完成抽象⽅法
5)针对抽象⽅法完成对应的l中的映射或者使⽤注解实现
6)运⾏时加载配置,产⽣SqlSessionFactory对象,然后调⽤openSession⽅法获取SqlSession,然后拿到Mappper接⼝代理对象,调⽤⽅法完成操作。
7)关闭会话
23. MyBatis中的关联如何实现?
1)⼀般使⽤< association>标签进⾏⼀对⼀的对象关联映射
2)使⽤< collection>标签进⾏⼀对多的集合关联映射具体映射时候可以采⽤⼀次性查询出结果(推荐)然后映射,也可以采⽤嵌套的select查询⽅式。24. MyBatis中的插件如何实现?
插件也可以理解为,即在mybatis执⾏某个sql语句或者结果处理前后,均可以⾃⼰编写代码进⾏额外的操作,Mybatis 仅可以编写针对 ParameterHandle r、ResultSetHandler、StatementHandler、Executor 这 4 种接⼝的插件。Mybatis 使⽤ JDK 的动态代理,为需要拦截的接⼝⽣成代理对象以实现接⼝⽅法拦截功能,每当执⾏这 4 种接⼝对象的⽅法时,就会进⼊拦截⽅法,具体就是 InvocationHandler 的 invoke()⽅法,只会拦截那些你指定需要拦截的⽅法,具体使⽤时还需要在类上进⾏签名以及在主配置⽂件中声明才能使⽤。
25. 请描述MyBatis中的优缺点?
1) MyBatis的优点:屏蔽jdbc api的底层访问细节;⾃⼰定制sql能⾃定义映射,和将sql语句与java代码进⾏分离;提供了将结果集⾃动封装称为实体对象和对象的集合的功能,queryForList返回对象集合,⽤queryForObject返回单个对象;提供了⾃动将实体对象的属性传递给sql语句的参数。其次mybatis很好的跟sprin g集成。
2) Mybatis的缺点:SQL 语句的编写⼯作量较⼤,尤其当字段多、关联表多时,对开发⼈员编写SQL 语句的功底有⼀定要求,SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
26. 请描述MyBatis如何进⾏批量操作?
mybatis中提供了<foreach>标签,可以对集合、数组进⾏循环,从⽽实现动态的批量操作
27. 请描述MyBatis如何获取⾃增的主键值?
Mybatis中可以在<insert>标签中添加usegeneratedkeys=”true” keyproperty=”id”属性获取⾃增后的主键值,⽐如增加操作时传⼊的实体对象没有id,调⽤带有该属性的增加操作后,则会将⾃增主键放⼊实体对象中。
也可以在<insert>标签中使⽤<selectKey>标签查询获取⾃增主键列数据。
28. 请描述MyBatis的Mapper功能⽅法如何传递多个参数?
Mybatis如果参数是⼀个,或者实体对象,则直接可以使⽤#{名称或属性}取出对应的数据,那么如果不是实体对象,但是有多个参数,实现如下:1)使⽤Map 集合封装传递的多个参数,因为map有键作为名称。2)使⽤@Param注解实现参数名的标注。 28. Hibernate如何实现分页查询?技巧:hibernate
实现分页的关键是通过⽅⾔的⽅式隔离数据差异,在分页处理上,由于各种数据库处理差异很⼤,未在hql中实现相应关键字,是利⽤查询接⼝两个关键⽅法完成(setFirstResult,s etMaxResult),说明这两个⽅法是关键。说明之后,可根据场景使⽤代码⽰例,进⼀步可阐述分页实现原理。Hibernate 实现分页查询的关键是两个⽅法 setFirs tResult: 设置第⼀数据开始位置setMaxResult :设置查询总记录数 29. @OneToMany注解的mappedBy属性有什么作⽤?技巧:mappedBy 属性的主要作⽤是告诉hibernate关联关系是通过对⽅外键引⽤完成关联映射,这⼀点必须说清楚。One的⼀⽅会成为主控⽅,加⼊mappedBy以后,就不会⽣成这两张关联表的中间表了,⽽是在Many的⼀⽅的表中⽣成⼀列作为外键。 30. MyBatis中的动态SQL是什么意思?MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们⽅便的在SQL语句中实现某些逻辑。
MyBatis中⽤于实现动态SQL的元素主要有:
if
choose(when,otherwise)
蓝奏云软件合集资料trim
where
set
后端开发模式foreach
29. hibernate中的update()和saveOrUpdate()的区别
1、update针对的是已存在的实体对象,数据库中如果没有实体所对应的数据记录,将会抛出异常;
2、saveOrUpdate()对象存在与否都不会有任何影响,有则更新,没则插⼊。
30. hibernate中对象的三种状态?
1、瞬时态:⽤new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫临时对象;
2、持久态:已经持久化,加⼊到了Session缓存中。如通过hibernate语句保存的对象。处于此状态的对象叫持久对象;
3、游离态(托管态): 持久化对象脱离了Session的对象。如Session缓存被清空的对象。特点:已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;
31. 如何理解Hibernate的延迟加载机制?在实际应⽤中,延迟加载与Session关闭的⽭盾是如何处理。
延迟加载就是并不是在读取的时候就把数据加载进来,⽽是等到使⽤时再加载。Hibernate使⽤了虚拟代理机制实现延迟加载,我们使⽤Session的load()⽅法加载数据或者⼀对多关联映射在使⽤延迟加载的情况下从⼀的⼀⽅加载多的⼀⽅,得到的都是虚拟代理,简单的说返回给⽤户的并不是实体本⾝,⽽是实体对象的代理。代理对象在⽤户调⽤getter⽅法时才会去数据库加载数据。但加载数据就需要数据库连接。⽽当我们把会话关闭时,数据库连接就同时关闭了。
延迟加载与session关闭的⽭盾⼀般可以这样处理:
①关闭延迟加载特性。这种⽅式操作起来⽐较简单,因为Hibernate的延迟加载特性是可以通过映射⽂件或者注解进⾏配置的,但这种解决⽅案存在明显的缺陷。⾸先,出现"no session or session was closed"通常说明系统中已经存在主外键关联,如果去掉延迟加载的话,每次查询的开销都会变得很⼤。
②在session关闭之前先获取需要查询的数据,可以使⽤⼯具⽅法Hibernate.isInitialized()判断对象是否被加载,如果没有被加载则可以使⽤Hibernate.initialize()⽅法加载对象。
③使⽤或过滤器延长Session的⽣命周期直到视图获得数据。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是这种做法。
32. session的load()和get()的区别?
1、get()采⽤⽴即加载⽅式;⽽load()采⽤延迟加载;
2、get()⽅法执⾏的时候,会⽴即向数据库发出查询语句,⽽load()⽅法返回的是⼀个代理(此代理中只有⼀个id属性),只有等真正使⽤该对象属性的时候,才会发出sql语句;
3、如果数据库中没有对应的记录,get()⽅法返回的是null。⽽load()⽅法出现异常ObjectNotFoundException 。
33. 介绍⼀下Hibernate的⼆级缓存。
1、按照以下思路来回答:(1)⾸先说清楚什么是缓存,(2)再说有了hibernate的Session就是⼀级缓存,即有了⼀级缓存,为什么还要有⼆级缓存,(3)最后再说如何配置Hibernate的⼆级缓存。
2.1、缓存就是把以前从数据库中查询出来和使⽤过的对象保存在内存中,当以后要使⽤某个对象时,先查询缓存中是否有这个对象,如果有则使⽤缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使⽤。
mysql面试题sql优化2.2、Hibernate中Session内置了⼀种缓存,我们通常将之称为Hibernate的⼀级缓存(Session级别的)
,当想使⽤session从数据库中查询出⼀个对象时,Ses sion也是先从⾃⼰内部查看是否存在这个对象,存在则直接返回,不存在才去访问数据库,并将查询的结果保存在⾃⼰内部。由于Session代表⼀次会话过程,⼀个Session与⼀个数据库连接相关连,所以Session最好不要长时间保持打开,通常仅⽤于⼀个事务当中,在事务结束时就应关闭。
2.3、⼆级缓存是SessionFactory级别的缓存,能被此SessionFactory⾥的所有Session共享。多个⼚商和组织都提供有缓存产品,例如,EHCache和OSCache 等等。在Hibernate中使⽤⼆级缓存,⾸先就要在l配置⽂件中配置使⽤哪个⼚家的缓存产品,接着需要配置该缓存产品⾃⼰的配置⽂件,最后要配置Hibernate中的哪些实体对象要纳⼊到⼆级缓存的管理中。
34. 谈⼀谈Hibernate的⼀级缓存、⼆级缓存和查询缓存?
Hibernate的Session提供了⼀级缓存的功能,默认总是有效的,当应⽤程序保存持久化实体、修改持久化实体时,Session并不会⽴即把这种改变提交到数据库,⽽是缓存在当前的Session中,除⾮显⽰调⽤了Session的flush()⽅法或通过close()⽅法关闭Session。通过⼀级缓存,可以减少程序与数据库的交互,从⽽提⾼数据库访问性能。
SessionFactory级别的⼆级缓存是全局性的,所有的Session可以共享这个⼆级缓存。不过⼆级缓存默认是关闭的,需要显⽰开启并指定需要使⽤哪种⼆级缓存实现类(可以使⽤第三⽅提供的实现)。⼀
旦开启了⼆级缓存并设置了需要使⽤⼆级缓存的实体类,SessionFactory就会缓存访问过的该实体类的每个对象,除⾮缓存的数据超出了指定的缓存空间。
⼀级缓存和⼆级缓存都是对整个实体进⾏缓存,不会缓存普通属性,如果希望对普通属性进⾏缓存,可以使⽤查询缓存。查询缓存是将HQL或SQL语句以及它们的查询结果作为键值对进⾏缓存,对于同样的查询可以直接从缓存中获取数据。查询缓存默认也是关闭的,需要显⽰开启。
35. 简述Hibernate常见优化策略?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论