最后
这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
-
POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。
-
JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,
容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
(2)mapper标签
该标签的作用是加载映射的,加载方式有如下几种:
使用相对于类路径的资源引用,例如:
使用完全限定资源定位符(URL),例如:
使用映射器接口实现类的完全限定类名,例如:
将包内的映射器接口实现全部注册为映射器,例如:
(3)Properties标签
实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件
(4)typeAliases标签
类型别名是为Java 类型设置一个短的名字。原来的类型名称配置如下
配置typeAliases,为com.itbluebox.domain.User定义别名为user
上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名
3、知识小结
核心配置文件常用配置:
1、properties标签:该标签可以加载外部的properties文件
2、typeAliases标签:设置类型别名
3、mappers标签:加载映射配置
4、environments标签:数据源环境配置标签
<property name=“password” value=“${jdbc.password}”/2>
1、SqlSession工厂构建器SqlSessionFactoryBuilder
常用API:SqlSessionFactory build(InputStream inputStream)
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
String resource = “org/mybatis/builder/mybatis-config.xml”;
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
其中, Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。
2、SqlSession工厂对象SqlSessionFactory
SqlSessionFactory 有多个个方法创建 SqlSession 实例。常用的有如下两个:
3、SqlSession会话对象
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有:
T selectOne(String statement, Object parameter)
List selectList(String statement, Object parameter)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
操作事务的方法主要有:
void commit()
void rollback()
1、传统开发方式
(1)编写UserDao接口
public interface UserDao {
List findAll() throws IOException;
}
(2)编写UserDaoImpl实现
public class UserDaoImpl implements UserDao {
//查询所有shuju
public List findAll() throws IOException{
//加载配置文件
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
//创建作用域工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取会话对象
SqlSession sqlSession = sessionFactory.openSession();
List users = sqlSession.selectList(“userMapper.findAll”);
for (User user : users) {
System.out.println(user);
}
sqlSession.commit();
sqlSession.close();
return users;
}
}
(3)测试传统方式
@Test
public void testTraditionDao() throws IOException {
UserDao userDao = new UserDaoImpl();
List all = userDao.findAll();
System.out.println(all);
}
2、代理开发方式
(1)代理开发方式介绍
采用 Mybatis 的代理开发方式实现 DAO 层的开发,
这种方式是我们后面进入企业的主流。
Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),
由Mybatis 框架根据接口定义创建接口的动态代理对象,
代理对象的方法体同上边Dao接口实现类方法。
Mapper 接口开发需要遵循以下规范:
1、 Mapper.xml文件中的namespace与mapper接口的全限定名相同
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
(2)编写UserMapper接口
package cn.itbluebox.mapper;
import cn.itbluebox.domain.User;
public interface UserMapper {
User findById(Integer id);
}
(3)编辑cn.itbluebox.mapper.UserMapper.xml
将之前的配置全部清空
写入如下配置
select * from User where id = #{id}
(4)测试代理方式
@Test
public void testProxyDao() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findById(1);
System.out.println(user);
sqlSession.close();
}
3、手动对Dao进行实现:传统开发方式
代理方式对Dao进行实现:
UserMapper userMapper =
sqlSession.getMapper(UserMapper.class);
1、动态sql语句概述
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,
有些时候业务逻辑复杂时,我们的 SQL是动态变化的,
此时在前面的学习中我们的 SQL 就不能满足要求了。
参考的官方文档,描述如下:
2、动态 SQL 之<if>
我们根据实体类的不同取值,
使用不同的 SQL语句来进行查询。
比如在 id如果不为空时可以根据id查询,
如果username 不同空时还要加入用户名作为条件。
这种情况在我们的多条件组合查询中经常会碰到。
<select id=“findByCondition”
parameterType=“cn.itbluebox.domain.User”
resultType=“cn.itbluebox.domain.User”>
select * from User
and id = #{id}
and username = #{username}
(1)完善UserMapper
User findByCondition(User user);
(2)完善MyBatisTest当中创建testFindByCondition方法
1)当查询条件只有id存在时,控制台打印的sql语句如下:
@Test
public void testFindByCondition() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
user.setUsername(“张三”);
User us = userMapper.findByCondition(user);
System.out.println(us);
sqlSession.close();
}
2)当查询条件只有id存在时,控制台打印的sql语句如下:
@Test
public void testFindByCondition() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
User us = userMapper.findByCondition(user);
System.out.println(us);
sqlSession.close();
}
5、动态 SQL 之<foreach>
(1)循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)
。
编写UserMapper.xml
select * from User
#{id}
(2)完善UserMapper
ArrayList findByIds(int ids[]);
(3)完善MyBatisTest当中的testfindByIds方法
@Test
public void testfindByIds() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int[] ids = new int[]{2,4};
ArrayList users = userMapper.findByIds(ids);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
运行测试
(4)foreach标签的属性含义如下:
<foreach>
标签用于遍历集合,它的属性:
collection
:代表要遍历的集合元素,注意编写时不要写#{}
open
:代表语句的开始部分
close
:代表结束部分
item
:代表遍历集合的每个元素,生成的变量名(自定义任意名称)
sperator
:代表分隔符
6、SQL片段抽取
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
select * from User
where id = #{id}
and id = #{id}
and username = #{username}
#{id}
7、知识小结
MyBatis映射文件配置:
:查询
:插入
:修改
:删除
:where条件
:if判断
:循环
:sql片段抽取
1、typeHandlers标签(处理时间)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时
还是从结果集中取出一个值时
都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
下表描述了一些默认的类型处理器(截取部分)。
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。
具体做法为:
实现 org.apache.ibatis.type.TypeHandler
接口,
或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler
,
然后可以选择性地将它映射到一个JDBC类型。
例如需求:一个Java中的Date数据类型,
我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,
即java的Date与数据库的varchar毫秒值之间转换。
开发步骤:
-
定义转换类继承类
BaseTypeHandler<T>
-
覆盖4个未实现的方法,其中
setNonNullParameter
为java
程序设置数据到数据库的回调方法,getNullableResult
为查询时mysql
的字符串类型转换成java
的Type
类型的方法 -
在MyBatis核心配置文件中进行注册
-
测试转换是否正确
(1)创建MyDateTypeHandler 类
package cn.itbluebox.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class MyDateTypeHandler extends BaseTypeHandler {
//将Java 类型转换为数据库需要的类型
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
long time = date.getTime();
preparedStatement.setLong(i,time);
}
//将数据中的类型 转换为java类型
//String 类型 要转换的字段名称
//ResultSet 查询出的结果集
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
//获得结果集中需要的数据(long)转换为Date
long aLong = resultSet.getLong(s);
Date date = new Date(aLong);
return date;
}
//将数据库当中的类型 转换为Java的类型
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
long aLong = resultSet.getLong(i);
Date date = new Date(aLong);
return date;
}
//将数据库中的类型 转换为Java类型
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
long aLong = callableStatement.getLong(i);
Date date = new Date(aLong);
return date;
}
}
(2)typeHandlers标签
(3)修改数据表和实体类User
package cn.itbluebox.domain;
import java.util.Date;
public class User {
private int id;
private String username;
private String password;
private Date birthday;
public User() {
}
public User(int id, String username, String password, Date birthday) {
this.id = id;
this.username = username;
this.password = password;
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return “User{” +
“id=” + id +
“, username='” + username + ‘’’ +
“, password='” + password + ‘’’ +
“, birthday=” + birthday +
‘}’;
}
}
(4)完善UserMapper
void save(User user);
(5)完善UserMapper.xml
insert into User values(#{id},#{username},#{password},#{birthday})
(6)完善MyBatisTest测试方法
//插入数据
@Test
public void testSaveUser()throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//创建user
User user = new User();
user.setUsername(“ceshi”);
user.setPassword(“abc”);
user.setBirthday(new Date());
//执行保存造作
mapper.save(user);
sqlSession.commit();
sqlSession.close();
}
运行测试
(7)测试查询操作
testFindByCondition刚刚写过的
2、plugins标签(处理分页)
MyBatis可以使用第三方的插件来对功能进行扩展,
分页助手PageHelper是将分页的复杂操作进行封装,
使用简单的方式即可获得分页的相关数据
开发步骤:
-
导入通用PageHelper的坐标
-
在mybatis核心配置文件中配置PageHelper插件
-
测试分页数据获取
(1)导入通用PageHelper坐标
com.github.pagehelper
pagehelper
3.7.5
com.github.jsqlparser
jsqlparser
0.9.1
(2)在mybatis核心配置文件中配置PageHelper插件
(3)UserMapper
ArrayList select();
(4)UserMapper.xml
(5)MyBatisTest
@Test
public void testPageHelper()throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(1,3);
ArrayList select = mapper.select();
for (User user : select) {
System.out.println(user);
}
sqlSession.commit();
sqlSession.close();
}
(6)获得分页相关的其他参数
//其他分页的数据
PageInfo pageInfo = new PageInfo(select);
System.out.println(“总条数:”+pageInfo.getTotal());
System.out.println(“总页数:”+pageInfo.getPages());
System.out.println(“当前页:”+pageInfo.getPageNum());
System.out.println(“每页显示长度:”+pageInfo.getPageSize());
System.out.println(“是否第一页:”+pageInfo.isIsFirstPage());
System.out.println(“是否最后一页:”+pageInfo.isIsLastPage());
3、知识小结
MyBatis核心配置文件常用标签:
1、properties标签:该标签可以加载外部的properties文件
2、typeAliases标签:设置类型别名
3、environments标签:数据源环境配置标签
4、typeHandlers标签:配置自定义类型处理器
5、plugins标签:配置MyBatis的插件
1、一对一查询
(1)一对一查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
(2)一对一查询的语句
对应的sql语句:select * from orders o,user u where o.uid=u.id;
查询的结果如下:
(3)创建Orders实体以及数据库表
在orders表当中添加一些数据
package cn.itbluebox.domain;
import java.util.Date;
public class Orders {
private int id;
private Date ordertime;
private double total;
//代表当前订单从属于哪一个客户
private User user;
public Orders() {
}
public Orders(int id, Date ordertime, double total, User user) {
this.id = id;
this.ordertime = ordertime;
this.total = total;
this.user = user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getOrdertime() {
return ordertime;
}
public void setOrdertime(Date ordertime) {
this.ordertime = ordertime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return “Order{” +
“id=” + id +
“, ordertime=” + ordertime +
“, total=” + total +
“, user=” + user +
‘}’;
}
}
(4)创建OrderMapper接口
package cn.itbluebox.mapper;
import cn.itbluebox.domain.Orders;
import java.util.List;
public interface OrderMapper {
List findAll();
}
(5) 配置OrderMapper.xml
select * from orders o,user u where o.id = u.id
(6)在sqlMapConfig.xml当中引入OrderMapper.xml配置文件
(7)OrderTest当中的testFindOrderAll
package cn.itbluebox.test;
import cn.itbluebox.domain.Orders;
import cn.itbluebox.mapper.OrderMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class OrderTest {
@Test
public void testFindOrderAll() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List all = mapper.findAll();
for (Orders order : all) {
System.out.println(order);
}
sqlSession.commit();
sqlSession.close();
}
}
2、一对多查询
(1)一对多查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
(2)一对多查询的语句
对应的sql语句:select *,o.id oid from user u left join orders o on u.id=o.uid;
查询的结果如下
(3)修改User实体
package cn.itbluebox.domain;
import com.sun.org.apache.xpath.internal.operations.Or;
import java.util.Date;
import java.util.List;
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//带代表当前用户具备的哪些订单
private List ordersList;
public User() {
}
public User(int id, String username, String password, Date birthday, List ordersList) {
this.id = id;
this.username = username;
this.password = password;
this.birthday = birthday;
this.ordersList = ordersList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public List getOrdersList() {
return ordersList;
}
public void setOrdersList(List ordersList) {
this.ordersList = ordersList;
}
@Override
public String toString() {
return “User{” +
“id=” + id +
“, username='” + username + ‘’’ +
“, password='” + password + ‘’’ +
“, birthday=” + birthday +
“, ordersList=” + ordersList +
‘}’;
}
}
(5)修改Orders表
(6)在创建UserMapper当中创建findUserAll()
List findUserAll();
(7)在配置UserMapper.xml
select *,o.id oid from user u left join orders o on u.id=o.uid;
(8)MyBatisTest当中的testUserAll
@Test
public void testUserAll() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream(“sqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List all = mapper.findUserAll();
for (User user : all) {
System.out.println(user.getUsername());
List ordersList = user.getOrdersList();
for (Orders orders : ordersList) {
System.out.println(orders);
}
System.out.println(“----------------------”);
}
sqlSession.commit();
sqlSession.close();
}
3、多对多查询
(1)多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
(2)多对多查询的语句
对应的sql语句:
select u.,r.,r.id rid
from user u left join user_role ur on u.id=ur.user_id
inner join role r on ur.role_id=r.id;
查询的结果如下:
(3)创建Role实体,创建Role表
package cn.itbluebox.domain;
public class Role {
private int id;
private String roleName;
private String roleDesc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return “Role{” +
“id=” + id +
“, roleName='” + roleName + ‘’’ +
“, roleDesc='” + roleDesc + ‘’’ +
‘}’;
}
}
(4)修改User实体
写在最后
很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。
最后祝愿各位身体健康,顺利拿到心仪的offer!
由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里
](https://img-blog.csdnimg.cn/d50d24df5be24ff2b1f5ee108ad8f6f7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6JOd55uS5a2QaXRibHVlYm94,size_20,color_FFFFFF,t_70,g_se,x_16)
3、多对多查询
(1)多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
(2)多对多查询的语句
对应的sql语句:
select u.,r.,r.id rid
from user u left join user_role ur on u.id=ur.user_id
inner join role r on ur.role_id=r.id;
查询的结果如下:
(3)创建Role实体,创建Role表
package cn.itbluebox.domain;
public class Role {
private int id;
private String roleName;
private String roleDesc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return “Role{” +
“id=” + id +
“, roleName='” + roleName + ‘’’ +
“, roleDesc='” + roleDesc + ‘’’ +
‘}’;
}
}
(4)修改User实体
写在最后
很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。
最后祝愿各位身体健康,顺利拿到心仪的offer!
由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里
[外链图片转存中…(img-0t0xsat7-1715292893914)]
[外链图片转存中…(img-sV59v0iY-1715292893914)]
[外链图片转存中…(img-1YnAd5Qx-1715292893915)]