10.29Mybatis框架学习
Posted 俊king
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.29Mybatis框架学习相关的知识,希望对你有一定的参考价值。
章节内容
Mybatis
是什么?
Mybatis
环境配置
什么是Mybatis
?
概念:
一个开源、轻量级的数据持久化框架
支持定制化 SQL、存储过程以及高级映射,可以在实体类和 SQL 语句之间建立映射关系,是一种半自动化的 ORM 实现。
优点:
-
内部封装了 JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程
-
性能优秀、小巧、简单易学、应用广泛
什么是ORM
概念:
ORM(Object Relational Mapping,对象关系映射)是一种数据持久化技术
特点:
通过JavaBean
对象去操作数据库
什么是持久化
将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中数据模型的统称。
举例:
文件的存储、数据的读取以及对数据表的增删改查等都是数据持久化操作。
核心要点
MyBatis 的主要思想是将程序中的大量 SQL 语句剥离出来,使用 XML 文件或注解的方式实现 SQL 的灵活配置,将 SQL 语句与程序代码分离,在不修改程序代码的情况下,直接在配置文件中修改 SQL 语句。
Mybatis
安装
包括:
-
Mybatis
下载 -
Mybatis
目录结构
由于自己是使用Maven
进行包管理的。所以:
<!--导入Mybatis依赖-->
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
</dependencies>
Mybatis
文件目录结构包括:
名称 | 说明 |
---|---|
asm-7.1.jar | 操作Java字节码的类库 |
cglib-3.3.0.jar | 用来动态继承Java类或实现接口 |
commons-logging-1.2.jar | 用于通用日志处理 |
javassist-3.27.0-GA.jar | 分析、编码和创建Java类库 |
log4j-1.2.17.jar | 日志系统 |
log4j-api-2.13.3.jar | log4j到log4j2的桥接包 |
log4j-core-2.13.3.jar | log4j到log4j2的桥接包 |
ognl-3.2.14.jar | OGNL的类库 |
slf4j-api-1.7.30.jar | 日志系统的封装,对外提供统一的API接口 |
slf4j-log4j12-1.7.30.jar | slf4j 对 log4j 的相应驱动,完成 slf4j 绑定 log4j |
Mybatis
项目的目录结构
这里是下面的项目的目录结构:
/MybatisStudy
/.idea
/src
/main
/java
/resources
/webapp
/WEB-INF
/test
/target
创建Mybatis
程序的步骤:
-
导入依赖--->编写
Mybatis
核心配置文件--->创建实体类--->创建DAO
接口--->创建SQL
Mybatis框架学习笔记
本篇Mybatis框架学习笔记;紧跟之前的学习
Mybatis框架学习笔记(2)—>
在mybatis框架核心配置文件中需要学习的配置
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
文章目录
1.关于在sql语句中使用 #{} 与${} 的区别
使用 #{}
回忆一下整理第一篇笔记时,当时的mapper.xml配置文件中,添加用户的sql;
当时用的是 #{ }
来得到对象中的值
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--注意 这里对应空间为持久层映射接口-->
<mapper namespace="com.xiaozhi.mapper.UserMapper">
<!--添加新用户的sql-->
<!--这里的parameterType 参数类型 就用刚才配置的别名 user了-->
<insert id="addUser" parameterType="user">
insert into t_user(account,password,address)
values (#{account},#{password},#{address})
</insert>
</mapper>
测试使用
@Test
public void testAddUser(){
//创建用户对象;
User user = new User("点金手","431231w","四川成都");
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用方法;这里实际上会执行sql语句;
mapper.addUser(user);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
可以看看测试打印的日志;
出现了占位符 ?,?,?
也就是说,他用了
PreparedStatement
来进行执行sql的;是比较安全的;可防止sql注入
使用${}
实际上,也可以用${ } ;
Ok,那就来试试;
在UserMapper.xml
中更换sql
<insert id="addUser" parameterType="user">
insert into t_user(account,password,address)
values (${account},${password},${address})
</insert>
执行测试
//使用${}方式传递参数执行sql;
@Test
public void testAddUser2(){
//创建用户对象;
User user = new User("阿飞","123132","四川成都");
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用方法;这里实际上会执行sql语句;
mapper.addUser(user);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行,诶,出现错误了;它直接把输入的赋值直接写到sql语句里面了; 而且是把输入的赋值当做数据库的列名了;所以首先提示找不到列名为 阿飞 的列;这里已经错了后面的自然不会再执行下去了;
要知道,这几个属性赋值的时候是字符串哦;在数据库中字符串赋值的时候,要加''
或者""
;
那么,修改一下sql语句吧
<insert id="addUser" parameterType="user">
insert into t_user(account,password,address)
values ('${account}','${password}','${address}')
</insert>
再次执行;
OK,执行成功了;
添加时;它是直接按拼接字符串的方式;将对象赋值给传递进去了;
${}
方式执行sql时,实际上是Statement
的方式;也就是说不安全的那个; 不能防止SQL注入
但是;${}
也是可以使用的,
因为用${}
传递的是列名,而不是传递数据;
2.在执行sql后,获取到数据表的主键值;
在之前进行的添加用户中,由于当时数据表的ID是作为主键自动递增的;
在执行完添加语句后,我想快速的得到这个刚刚添加的数据的ID;
那么直接获取Id,得到的肯定是0
啊;
试试看—>
//在添加用户数据之后,立即得到主键ID的值;
@Test
public void testAddUser3(){
//创建用户对象;
User user = new User("爱喝水","123132","陕西西安");
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用方法;这里实际上会执行sql语句;
mapper.addUser(user);
System.out.println("当前的用户Id值为-->"+user.getId());
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行一下;用户肯定存入了;但是这里输出得到的ID是0;
看看数据表,该用户的ID是24哦
当然,可以写两个sql语句;就是说,刚刚添加的新用户数据之后,然后我又去根据用户的某个信息查询得到他的ID信息;这种方式是可行的;
但是,还有一种个比较好的方式,在执行sql语句后,不需要去另外执行别的sql语句;也能得到用户的ID;
那就是在UserMapper.xml
的配置文件中,写sql语句的时候;将参数useGeneratedKeys
设置为true;即使用生成的主键;当然还要设置数据库的列名和类中的属性对应;
<!--在执行后,想要得到数据表的主键值 确认使用主键 数据表的列名 实体类的对应属性-->
<insert id="addUser" parameterType="user" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into t_user(account,password,address)
values (#{account},#{password},#{address})
</insert>
再次测试执行;
//在添加用户数据之后,立即得到主键ID的值;
@Test
public void testAddUser4(){
//创建用户对象;
User user = new User("小咸鱼","123132","四川成都");
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用方法;这里实际上会执行sql语句;
mapper.addUser(user);
System.out.println("当前的用户Id值为-->"+user.getId());
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行;得到了主键ID号
3.写个修改用户信息
用户的实体类,改变一下,也就是添加个新的有参构造方法;以及toString()方法
package com.xiaozhi.pojo;
/**
* @author by CSDN@小智RE0
* @date 2021-10-24 22:07
* 实体类User(用户类)
*/
public class User {
//属性,id,账户,密码,地址;
private int id;
private String account;
private String password;
private String address;
//构造方法;
public User() {
}
public User(int id, String account, String password, String address) {
this.id = id;
this.account = account;
this.password = password;
this.address = address;
}
//这里构造方法初始化时就没包括ID;
public User(String account, String password, String address) {
this.account = account;
this.password = password;
this.address = address;
}
//getter,setter;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", account='" + account + '\\'' +
", password='" + password + '\\'' +
", address='" + address + '\\'' +
'}';
}
}
当然,首先在UserMapper
持久层接口定义方法;
//更新修改用户信息;
void updateUser(User user);
然后在UserMapper.xml
映射文件中编写对应的sql文件
<!--修改用户信息 参数为基本类型,可以不标注-->
<update id="updateUser">
update t_user set account=#{account},password=#{password},address=#{address}
where id=#{id}
</update>
测试执行
//修改用户信息;
@Test
public void updateUser(){
//创建用户对象;
User user = new User(25,"学习mybatis框架","12weds","陕西");
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用方法;
userMapper.updateUser(user);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行成功
4.写个删除用户
在UserMapper
持久层接口定义方法;
//根据ID删除用户;
void deleteUser(int id);
在UserMapper.xml
映射文件中编写对应的sql文件
<!--删除用户信息-->
<delete id="deleteUser">
delete from t_user where id=#{id}
</delete>
测试执行
//删除用户信息;
@Test
public void deleteUser(){
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用方法;
userMapper.deleteUser(20);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行;删除成功;
5.查询所有用户
在UserMapper
持久层接口定义方法;
//查询所有用户;
List<User> findUser();
在UserMapper.xml
映射文件中编写对应的sql文件
<!--查询所有用户-->
<select id="findUser" resultType="user">
select * from t_user
</select>
测试执行
//查询所有用户;
@Test
public void findAllUser(){
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用方法;
List<User> user = userMapper.findUser();
System.out.println(user);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行;
6.根据Id查询用户
在UserMapper
持久层接口定义方法;
//根据用户ID获取;
User findUserById(int id);
在UserMapper.xml
映射文件中编写对应的sql文件
<!--根据Id查询信息-->
<select id="findUserById" resultType="user">
select * from t_user where id=#{id};
</select>
测试执行
//根据Id查询用户信息;
@Test
public void findUserById(){
//使用工具类创建sqlSession;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用方法;
User userById = userMapper.findUserById(25);
System.out.println(userById);
//事务提交;
sqlSession.commit();
//关闭sqlSession;
sqlSession.close();
}
执行成功;
7.配置开启驼峰命名匹配
有没有注意到;前面在查询信息时,没有进行指定要获取的指定属性;它就自动匹配到用户类的对象属性中了;这是由于当时写实体类时,把属性名和数据库的列名一致了
那么,我要是数据表的列名和用户类的属性不相同了呢?
比如说,这里我把用户类的地址属性改了原来是address
;现在我把它改成addRess
,驼峰命名的方式;
package com.xiaozhi.pojo;
/**
* @author by CSDN@小智RE0
* @date 2021-10-27 1:48
* 实体类User(用户类)
*/
public class User {
//属性,id,账户,密码,地址;
private int id;
private String account;
private String password;
private String addRess;
//构造方法;
public User() {
}
public User(int id, String account, String password, String addRess) {
this.id = id;
this.account = account;
this.password = password;
this.addRess = addRess;
}
//这里构造方法初始化时就没包括ID;
public User(String account, String password, String addRess) {
this.account = account;
this.password = password;
this.addRess = addRess;
}
//getter,setter;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddRess() {
return addRess;
}
public void setAddRess(String addRess) {
this.addRess = addRess;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", account='" + account + '\\'' +
", password='" + password + '\\'' +
", addRess='" + addRess + '\\'' +
'}';
}
}
然后我把数据表的地址由address
改为了add_ress
这时我再根据ID查询信息时,地址查不到信息;
实际上,这里需要在mybatis的核心配置文件mybatis-config.xml
中进行一个设置
在settings
下配置mapUnderscoreToCamelCase
为true
是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
它默认为false关闭状态的;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config
3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入外部的资源文件-->
<properties resource="database.properties">
</properties>
<settings>
<!--配置日志-->
<setting name以上是关于10.29Mybatis框架学习的主要内容,如果未能解决你的问题,请参考以下文章