标签:类型 app strong stat primary character repos 工作量 values
MyBatis 最初的设计是基于 XML 配置文件的,但随着 Java 的发展(Java 1.5 开始引入注解)和 MyBatis 自身的迭代升级,终于在 MyBatis 3 之后就开始支持基于注解的开发了。
下面我们使用 Spring Boot + MyBatis 注解的方式,来实现对数据库的基本操作,具体实现步骤如下。
drop table if exists `t\_user`;
create table `t\_user` (
`id` bigint(20) not null auto_increment comment '主键id',
`username` varchar(32) default null comment '用户名',
`password` varchar(32) default null comment '密码',
`nick\_name` varchar(32) default null,
primary key (`id`)
) engine=innodb auto_increment=1 default charset=utf8;
\<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --\>
\<dependency\>
\<groupId\>org.mybatis.spring.boot\</groupId\>
\<artifactId\>mybatis-spring-boot-starter\</artifactId\>
\<version\>2.1.0\</version\>
\</dependency\>
\<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --\>
\<dependency\>
\<groupId\>mysql\</groupId\>
\<artifactId\>mysql-connector-java\</artifactId\>
\<version\>8.0.16\</version\>
\</dependency\>
在 application.yml 文件中添加以下内容:
spring:
datasource:
url: jdbc:mysql://localhost:3306/learndb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
type-aliases-package: com.interview.model
public class UserEntity implements Serializable {
private static final long serialVersionUID = -5980266333958177105L;
private Integer id;
private String userName;
private String passWord;
private String nickName;
public UserEntity(String userName, String passWord, String nickName) {
this.userName = userName;
this.passWord = passWord;
this.nickName = nickName;
}
public Integer getId() {
return id;
}
public void setId(Integer 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 String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
}
public interface UserMapper {
@Select("select \* from t\_user")
@Results({
@Result(property = "nickName", column = "nick\_name")
})
List\<UserEntity\> getAll();
@Select("select \* from t\_user where id = \#{id}")
@Results({
@Result(property = "nickName", column = "nick\_name")
})
UserEntity getOne(Long id);
@Insert("insert into t\_user(username,password,nick\_name) values(\#{userName}, \#{passWord}, \#{nickName})")
void insert(UserEntity user);
@Update("update t\_user set username=\#{userName},nick\_name=\#{nickName} where id =\#{id}")
void update(UserEntity user);
@Update({"\<script\> ",
"update t\_user ",
"\<set\>",
" \<if test='userName != null'\>userName=\#{userName},\</if\>",
" \<if test='nickName != null'\>nick\_name=\#{nickName},\</if\>",
" \</set\> ",
"where id=\#{id} ",
"\</script\>"})
void updateUserEntity(UserEntity user);
@Delete("delete from t\_user where id =\#{id}")
void delete(Long id);
}
使用 @Select、@Insert、@Update、@Delete、@Results、@Result 等注解来替代 XML 配置文件。
在启动类中添加 @MapperScan,设置 Spring Boot 启动的时候会自动加载包路径下的 Mapper。
@SpringBootApplication
@MapperScan("com.interview.mapper")
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class, args);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
userMapper.insert(new UserEntity("laowang", "123456", "老王"));
Assert.assertEquals(1, userMapper.getAll().size());
}
}
答:MyBatis 优缺点如下:
优点:
缺点:
总体来说,MyBatis 是一个非常不错的持久层解决方案,它专注于 SQL 本身,非常灵活,适用于需求变化较多的互联网项目,也是当前国内主流的 ORM 框架。
A:可以灵活的编辑 SQL 语句
B:很好的支持不同数据库之间的迁移
C:能够很好的和 Spring 框架集成
D:提供映射标签支持对象和数据库的字段映射
答:B
题目解析:因为 MyBatis 需要自己编写 SQL 语句,但每个数据库的 SQL 语句有略有差异,所以 MyBatis 不能很好的支持不同数据库之间的迁移。
答:MyBatis 和 Hibernate 都是非常优秀的 ORM 框架,它们的区别如下:
$
”有什么区别?答:“#”是预编译处理,“$”是字符替换。 在使用“#”时,MyBatis 会将 SQL 中的参数替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入,保证程序的运行安全。
答:通常的解决方案有以下两种方式。
① 在 SQL 语句中重命名为实体类的属性名,可参考以下配置:
\<select id="selectorder" parametertype="int" resultetype="com.interview.order"\>
select order_id id, order_no orderno form order where order_id=#{id};
\</select\>
② 通过 <resultMap>
映射对应关系,可参考以下配置:
\<resultMap id="BaseResultMap" type="com.interview.mybatislearning.model.UserEntity" \>
\<id column="id" property="id" jdbcType="BIGINT" /\>
\<result column="username" property="userName" jdbcType="VARCHAR" /\>
\<result column="password" property="passWord" jdbcType="VARCHAR" /\>
\<result column="nick\_name" property="nickName" jdbcType="VARCHAR" /\>
\</resultMap\>
\<select id="getAll" resultMap="BaseResultMap"\>
select * from t_user
\</select\>
答:可以在 Java 代码中添加 SQL 通配符来实现 like 查询,这样也可以有效的防治 SQL 注入,具体实现如下:
Java 代码:
String name = "%wang%":
List<User> list = mapper.likeName(name);
Mapper 配置:
\<select id="likeName"\>
select * form t_user where name like #{name};
\</select\>
答:MyBatis 的分页方式有以下两种:
答:RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据。因为 MyBatis 是对 JDBC 的封装,在 JDBC 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在执行 next() 的时候,去查询更多的数据。 就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,要取 4 次才能把钱取完。对于 JDBC 来说也是一样,这样做的好处是可以有效的防止内存溢出。
答:因为使用 HashMap 或 Hashtable 作为查询结果集直接输出,会导致值类型不可控,给调用人员造成困扰,给系统带来更多不稳定的因素。
答:动态 SQL 是指可以根据不同的参数信息来动态拼接的不确定的 SQL 叫做动态 SQL,MyBatis 动态 SQL 的主要元素有:if、choose/when/otherwise、trim、where、set、foreach 等。 以 if 标签的使用为例:
<select id="findUser" parameterType="com.interview.entity.User" resultType="com.interview.entity.User">
select * from t_user where
<if test="id!=null">
id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
</select>
答:因为事务的滥用会影响数据的 QPS(每秒查询率),另外使用事务的地方还要考虑各方面回滚的方案,如缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
答:只需要在 mybatis-config.xml 设置 <setting name="lazyLoadingEnabled" value="true"/>
即可打开延迟缓存功能,完整配置文件如下:
\<configuration\>
\<settings\>
\<!-- 开启延迟加载 --\>
\<setting name="lazyLoadingEnabled" value="true"/\>
\</settings\>
\</configuration\>
答:MyBatis 缓存如下:
手动开启二级缓存,配置如下:
\<configuration\>
\<settings\>
\<!-- 开启二级缓存 --\>
\<setting name="cacheEnabled" value="true"/\>
\</settings\>
\</configuration\>
答:可直接在 XML 中配置开启 EhcacheCache,代码如下:
\<mapper namespace="com.interview.repository.ClassesReposirory"\>
\<!-- 开启二级缓存 --\>
\<cache type="org.mybatis.caches.ehcache.EhcacheCache" \>
\<!-- 缓存创建以后,最后一次访问缓存的时间至失效的时间间隔 --\>
\<property name="timeToIdleSeconds" value="3600"/\>
\<!-- 缓存自创建时间起至失效的时间间隔--\>
\<property name="timeToLiveSeconds" value="3600"/\>
\<!-- 缓存回收策略,LRU 移除近期最少使用的对象 --\>
\<property name="memoryStoreEvictionPolicy" value="LRU"/\>
\</cache\>
\<select id="findById" parameterType="java.lang.Long" resultType="com.interview.entity.Classes"\>
select * from classes where id = #{id}
\</select\>
\</mapper\>
答:MyBatis 提供的连接器有以下 4 种。
拦截功能具体实现如下:
@Intercepts({@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class TestInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation.getTarget(); //被代理对象
Method method = invocation.getMethod(); //代理方法
Object[] args = invocation.getArgs(); //方法参数
// 方法拦截前执行代码块
Object result = invocation.proceed();
// 方法拦截后执行代码块
return result;
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
通过本文可以看出 MyBatis 注解版和 XML 版的主要区别是 Mapper 中的代码,注解版把之前在 XML 的 SQL 实现,全部都提到 Mapper 中了,这样就省去了配置 XML 的麻烦。
欢迎关注我的公众号,回复关键字“Java” ,将会有大礼相送!!! 祝各位面试成功!!!
%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png)
标签:类型 app strong stat primary character repos 工作量 values
原文地址:https://www.cnblogs.com/dailyprogrammer/p/12272564.html