Mybatis学习总结
学习的内容如下:
- 封装 MyBatis 简单工具类
- Mybatis 中带条件的查询
- 通过 Mybatis 完成增、删、改、查等操作
- Mybatis 中类型别名的配置
1、Mybatis 简单工具类的封装
public class MyBatisUtil {
// 声明工厂对象
private static SqlSessionFactory factory;
// 通过静态代码块对工厂进行初始化, 只初始化一次
static {
try {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("工厂无法初始化...");
}
}
/**
* 获取SqlSession对象
*
* @return
*/
public static SqlSession getSession() {
return factory.openSession();
}
}
2、Mybatis 中带条件的查询
在 Mybatis 中,提供了一些方法可以接受执行 SQL 语句时的参数,但是,不同形式的传参获取方式不同,获取方式有两种:
2.1、#{} 占位符
类似于 JDBC 中通过 PreparedStatement 进行操作的方式,会将 sql 语句中需要参数的位置使用 ? 进行占位,后续由传进来的参数进行参数的绑定,当使用 #{} 接收参数时,参数传递的方式有三种:
2.1.1、 简单类型参数的传递
简单类型指的是:基本数据类型、包装类型、String、java.sql.*等等;
当参数是基本数据类型时,Mybatis 会忽略 SQL 语句中参数的个数和占位符的名称,然后将参数进行自动绑定
parameterType属性可以定义参数的类型, 如果定义, 传参时要求参数类型必须和指定的类型一致, 否则抛出ClassCastException.
<mapper namespace="com.bjsxt.mapper">
<select id="selById" resultType="com.j9a.pojo.User">
select *
from tb_user
where id=#{id}
</select>
</mapper>
@Test
public void test1() {
SqlSession session = MyBatisUtil.getSession();
User user = session.selectOne("selById", "2");
System.out.println(user);
session.close();
}
2.1.2、 Map类型参数的传递
Map是KV结构, 可以通过key定位value
当参数是 Map 集合时, SQL 语句中的 #{} 里应该写 Map 集合的 key 值, MyBatis 会通过 key 值找到 value 然后进行参数绑定. 如果 key 不存在, 不会报错, 会使用 null 进行参数绑定.
<mapper namespace="com.bjsxt.mapper">
<select id="selByMap" resultType="com.j9a.pojo.User">
select *
from tb_user
where username=#{username} and password=#{password}
</select>
</mapper>
@Test
public void testLogin() {
SqlSession session = MyBatisUtil.getSession();
Map<String, String> params = new HashMap<>();
params.put("username", "zhangsan");
params.put("password", "123");
User user = session.selectOne("selByMap", params);
System.out.println(user);
session.close();
}
2.1.3、对象类型参数的传递
除了简单类型和Map类型以外的其他类型。
当参数是对象类型时, SQL语句中的#{}里应该写对象的getter方法对应的属性名. 当getter不存在时, 抛出异常:
<mapper namespace="com.bjsxt.mapper">
<select id="selByObject" resultType="com.j9a.pojo.User">
select *
from tb_user
where username=#{username1} and password=#{password}
</select>
</mapper>
@Test
public void testLogin2() {
SqlSession session = MyBatisUtil.getSession();
User params = new User();
params.setUsername("lisi");
params.setPassword("123");
User user = session.selectOne("selByObject", params);
System.out.println(user);
session.close();
}
2.2、${}占位符
类似于jdbc中通过Statement进行操作的方式, 会直接将传递的参数和SQL语句进行字符串的拼接. 一般当SQL语句结构不确定时使用.
<select id="sel2" resultType="com.j9a.pojo.User">
select *
from ${tableName}
where ${columnName}=${columnValue} order by ${order}
</select>
@Test
public void testSel2() {
SqlSession session = MyBatisUtil.getSession();
Map<String, Object> params = new HashMap<>();
params.put("tableName", "tb_user");
params.put("columnName", "age");
params.put("columnValue", 18);
params.put("order", "birthday desc");
List<User> list = session.selectList("sel2", params);
System.out.println(list);
session.close();
}
3、Mybatis 实现增、删、改(CUD)操作
CUD 操作会破坏数据库中原有的数据,所以必须要进行事务管理;
事务的四大特性ACID(原子性、一致性、隔离性、持久性);
JDBC中, 通过Connection对象对事务进行管理;
- 开启手动事务管理: Connection.setAutoCommit(false);
- 事务提交: Connection.commit();
- 事务回滚: Connection.rollback();
MyBatis中, 事务管理通过SqlSession对象进行.
mybatis默认的SqlSessionFactory是DefaultSqlSessionFactory,它openSession()的源码是:
public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
}
return var8;
}
可以看到,mybatis默认每次获取session都会开启一个事务,且不自动提交事务。如果更新操作完成后不手动commit,则在连接断开时会将更新操作回滚。
SqlSession session = MybatisUtil.getSession(); // 通过Mybatis封装工具类获取 SqlSession对象
UserMapper userMapper = session.getMapper(UserMapper.class);
try{
UserDomain newUserDomain = new UserDomain();
newUserDomain.setAge(10);
newUserDomain.setName("scp2");
newUserDomain.setSchool("高中");
userMapper.insert(newUserDomain);
session.commit();// 手动commit 如果不commit,连接断开时操作会被回滚
}
catch (Exception e){
System.out.println(e);
}
finally {
if (null != session) {session.close();}
}
3.1、增
<insert id="insUser">
insert into tb_user values (default, #{username}, #{password}, #{realname},
#{age}, #{birthday}, #{regTime})
</insert>
@Test
public void testAdd() {
SqlSession session = MyBatisUtil.getSession(); // 通过SqlSession操作数据库
User user = new User();
user.setUsername("wukong");
user.setPassword("111");
user.setRealname("悟空");
user.setAge(10);
user.setRegTime(new Date());
try {
session.insert("insUser", user);
session.commit(); // 手动commit
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}
session.close();
}
3.2、改
<update id="updateUser">
update tb_user
set age=#{age}
where id=#{id}
</update>
@Test
public void testUpd() {
SqlSession session = MyBatisUtil.getSession(); // 通过SqlSession操作数据库
Map<String, Object> map = new HashMap<>();
map.put("age", 10);
map.put("id", 2);
try {
session.update("updateUser", map);
session.commit(); // 手动commit
} catch (Exception e) {
session.rollback();
e.printStackTrace();
}
session.close();
}
3.3、删除
<delete id="deleteUser">
delete from tb_user where id=#{id}
</delete>
@Test
public void testDel() {
SqlSession session = MyBatisUtil.getSession(); // 通过SqlSession操作数据库
try {
session.delete("deleteUser", 3);
session.commit(); // 手动commit
} catch (Exception e) {
session.rollback();
e.printStackTrace();
}
session.close();
}
4、Mybatis 类型别名配置
在mybatis的配置文件中加上以下内容;
<typeAliases>
<!--<typeAlias type="com.j9a.pojo.User" alias="u" />-->
<package name="com.bjsxt.pojo" />
</typeAliases>
4.1、密码加密
package com.j9a.util;
import java.security.MessageDigest;
public class Md5Util {
/**
* 接收一个明文密码, 返回加密以后的密文
** @param pwd
* @return
*/
public static String md5(String pwd) throws Exception {
// 创建MessageDigest对象
MessageDigest digest = MessageDigest.getInstance("MD5");
// 对明文进行加密
byte[] temp = digest.digest(pwd.getBytes());
// 准备StringBuilder用于保存结果
StringBuilder builder = new StringBuilder();
// 遍历字节数组, 一个字节转换为长度为2的字符串
for (byte b : temp) {
// 去除负数
String s = Integer.toHexString(b & 0xff);
// 补零
if(s.length() == 1) {
builder.append(0);
}
builder.append(s);
}
return builder.toString();
}
}