文章目录
- 一、今日内容
- 二、mybatis实现crud
- 2.1 搭建环境(配置文件参考a、网址)(顺便实现findAll查询)
- 目录结构:
- pom.xml
- User.java
- SqlMapConfig.xml
- UserMapper.xml (namespace写"userMapper"则dao都不需要了)
- TestMybatisCRUD.java
- 2.2 根据id查询
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法
- 2.3 添加
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法
- 此处引入日志:
- 2.4 修改
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法 更新
- 2.5 删除
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法
- 2.5 模糊查询
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法
- 2.5 查询总记录数
- UserMapper.xml sql的配置
- TestMybatisCRUD 测试方法
- mapper内子标签名无所谓
- 三、两种Dao开发
- 4.1 传统dao开发
- pom.xml
- UserMapper.xml
- SqlMapConfig.xml 同上略
- User.java同上略
- UserDao.java
- UserDaoImpl.java (和整合后的ssh一样,传入一个sessionFactory)
- TestMybatisDao.java
- 4.2 动态代理模式开发 (以后都用此==★==)
- pom.xml 同上
- SqlMapConfig.xml 同上
- UserDao 同上
- User 同上
- UserMapper.xml 写法有变
- TestMybatisProxy.java
- 动态代理小结:
- 四、核心配置文件详解
- 配置文件中的标签和顺序
- dtd约束
- properties文件分离数据库4大核心属性配置
- jdbc.properties
- SqlMapConfig.xml
- typeAliases 为类的全路径名取别名
- 单类型映射:
- SqlMapConfig.xml内取别名
- UserMapper.xml
- 包的映射(今后的写法★)
- SqlMapConfig.xml
- UserMapper.xml
- 框架预定义别名:TypeAliasRegistry类(写出来,ctrl+左击可看)
- eg:以后java.lang.Integer直接写int即可
- mappers不同引入方法
- 配置文件引入法
- dao接口引入法:
- 直接引入包名(相当于引入包下所有类)(今后写法★★ 最简单)
- UserDao.xml
- 五、输入参数类型和输出参数类型
- 各种参数类型
- 多条件查询:(其中的包装对象类型)
- 自定义新的javabean封装参数集合(麻烦 但适合团队协作开发)
- 各种参数集合放到map中(简单 但不适合团队协作开发 个人开发就用这个吧)
- 返回值类型(处理表列名和javabean属性名不一致)
- **UserMapper.xml ★**
- 六、小结 (很碎 需要整理 可当做串线)
一、今日内容
1、mybatis实现CRUD
2、两种Dao开发
3、核心配置文件详解
4、输入参数和输出参数
二、mybatis实现crud
a、mybatis 的中文文档网址:http://www.mybatis.org/mybatis-3/zh/getting-started.html (配置文件到入门里复制)
b、 selectList 查询多个对象,返回一个list集合(也能查询一个)
selectOne: 查询单个对象,返回一个对象
c、日志记录日常操作
引入依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
引入日志的配置文件:log4j.properties
d、增删改查
先写配置文件(主要是sql语句)
然后写测试类
e、模糊查询
参数: %a%
配置文件: username like #{username}
参数: a
配置文件1: username like “%”#{username}"%"
配置文件2: username like “%"${value}"%”
如果传的是简单类型必须使用value (value是关键字)
如果是pojo,属性名引用
f、参数
简单类型: 基本数据类型,String(不自带过多属性的类型)
如果${} 必须用value引用 (${}内部必须写value关键字)
如果#{} 随便写 (#{}内部可以随意写 #{hsdjhjhcsjbcfdb}都不影响程序运行)
pojo类型:必须写属性名引用(简单类型#{}可以随便写 类类型就全部得写属性名了)
g、${} 与 #{}区别
${}:直接拼接,不会转换类型, 不能防注入 (很死的拼接 不要用 string都不会帮你加""而直接拼接)
#{}:转换类型后拼接, 相当于占位符?,可以防注入
$一堆坑 ${username}必须写成 "${username}"才行 自己用就用#{}吧
#{}会读取类型 必要时自动进行类型转换 eg:String类型转Date存到mysql数据库 $就转换不了(很死的简单字符串拼接)
2.1 搭建环境(配置文件参考a、网址)(顺便实现findAll查询)
目录结构:
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--mybatis依赖:整个mybatis一个jar即可-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
User.java
package cn.ahpu.domain;
/**
* @author 寒面银枪
* @create 2020-01-07 12:45
*/
public class User {
private Integer id;
private String username;
private String password;
private String sex;
private String address;
//省略get/set
@Override
public String toString() {
return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}';
}
}
SqlMapConfig.xml
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisdb_331"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/ahpu/domain/UserMapper.xml"/>
</mappers>
</configuration>
UserMapper.xml (namespace写"userMapper"则dao都不需要了)
<?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="userMapper">
<select id="findAll" resultType="cn.ahpu.domain.User">
select * from user
</select>
</mapper>
TestMybatisCRUD.java
package cn.ahpu;
import cn.ahpu.domain.User;
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.InputStream;
import java.util.List;
/**
* @author 寒面银枪
* @create 2020-01-07 12:58
*
* 测试增删改查
*
*/
public class TestMybatisCRUD {
@Test
public void testFindAll(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行方法
List<User> userList = sqlSession.selectList("userMapper.findAll");//mapperId:namesapce+id (xxxMapper.XMl)
for (User user : userList) {
System.out.println(user);
}
//关闭资源 容易忘
sqlSession.close();
}
}
2.2 根据id查询
UserMapper.xml sql的配置
<!--根据id查询
id="findById"唯一标识
resultType="cn.ahpu.domain.User":返回值类型 (list集合单个元素类型)
parameterType:传入的参数类型
'?'在mybatis写法: 引入变量 #{}
-->
<select id="findById" resultType="cn.ahpu.domain.User" parameterType="java.lang.Integer">
select * from user where id = #{id}
</select>
TestMybatisCRUD 测试方法
@Test
public void testFindById(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//上面是固定代码
//执行方法一:返回list
//selectList 永远返回list集合
/* List<User> list = sqlSession.selectList("userMapper.findById", 1);
for (User user : list) {
System.out.println(user);
}*/
//findById肯定只有一个结果 返回一个list明显不合适
//执行方法二:返回单个对象
//selectOne():返回一个对象
User u = sqlSession.selectOne("userMapper.findById", 1);
System.out.println(u);
//别忘记关闭
sqlSession.close();
}
2.3 添加
UserMapper.xml sql的配置
<!--添加
不用写返回值类型
要写参数类型(插入的对象类型)
-->
<insert id="save" parameterType="cn.ahpu.domain.User">
insert into user values(null,#{username},#{password},#{sex},#{address})
</insert>
TestMybatisCRUD 测试方法
注意修改了数据库必须提交
@Test
public void testSave(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession(此处获取的sqlSession是不能自动提交的)
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行插入
User user=new User(null,"田七","tianqi","女","青霞派");
sqlSession.insert("userMapper.save", user);
//注意修改了数据库必须提交 ★
sqlSession.commit();
//关闭资源
sqlSession.close();
}
此处引入日志:
2.4 修改
UserMapper.xml sql的配置
<!--修改
参数也直接传入一个User即可 (和hibernate一样)
-->
<update id="update" parameterType="cn.ahpu.domain.User">
update user
set username=#{username},password=#{password},sex=#{sex},address=#{address}
where id=#{id}
</update>
TestMybatisCRUD 测试方法 更新
注意不同于hibernate(看sql语句就明白了) 不需要先查再改 可以直接设置id
@Test
public void testUpdate(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession(此处获取的sqlSession是不能自动提交的)
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行修改 注意不同于hibernate(看sql语句就明白了 不需要先查再改 可以直接设置id)
User user=new User(7,"田九","tianjiu","男","青霞派");
sqlSession.update("userMapper.update", user);
//注意修改了数据库必须提交 ★
sqlSession.commit();
//关闭资源
sqlSession.close();
}
2.5 删除
UserMapper.xml sql的配置
<!--删除-->
<delete id="delete" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
TestMybatisCRUD 测试方法
@Test
public void testDelete(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession(此处获取的sqlSession是不能自动提交的)
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行删除 根据id 删除7号 一切根据sql语句的逻辑来 一切以sql语句为中心
sqlSession.delete("userMapper.delete", 7);
//注意修改了数据库必须提交 ★
sqlSession.commit();
//关闭资源
sqlSession.close();
}
2.5 模糊查询
UserMapper.xml sql的配置
<!--根据姓名模糊查询-->
<!--<select id="findByUsername" parameterType="java.lang.String" resultType="cn.ahpu.domain.User">
select * from user where username like "%"#{username}"%"
</select>-->
<!--写法二-->
<select id="findByUsername" parameterType="java.lang.String" resultType="cn.ahpu.domain.User">
select * from user where username like "%${value}%"
</select>
TestMybatisCRUD 测试方法
/**
* 根据用户名模糊查询
*/
@Test
public void testFindByUsername(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//上面是固定代码
//List<User> list = sqlSession.selectList("userMapper.findByUsername", "%s%");//xml内不加%%
List<User> list = sqlSession.selectList("userMapper.findByUsername", "s");//xml内加%%
for (User user : list) {
System.out.println(user);
}
//别忘记关闭
sqlSession.close();
}
2.5 查询总记录数
UserMapper.xml sql的配置
<!--获取总记录数-->
<select id="findTotalCount" resultType="java.lang.Integer">
select count(*) from user
</select>
TestMybatisCRUD 测试方法
/*查询总记录数*/
@Test
public void testFindTotalCount(){
//获取输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//获取sqlsessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//selectOne():返回一个值
int n = sqlSession.selectOne("userMapper.findTotalCount");
System.out.println("总记录数:"+n);
//别忘记关闭
sqlSession.close();
}
mapper内子标签名无所谓
回想昨天的自定义框架,读取XXXMapper.xml文件时直接读取mapper标签下的所有子标签,然后根据namespace+id作为key,然后执行内部的sql语句,与子标签名无关,因此子标签名select、update、delete可以随便写,可以都写成select,不会影响程序运行结果,(最好区分开来写,便于人阅读)
可以测试将delete改成select仍然能删除
三、两种Dao开发
4.1 传统dao开发
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis_day02_1_crud</artifactId>
<groupId>cn.ahpu</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../mybatis_day02_1_crud/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis_day02_2_crud_dao</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
UserMapper.xml
<?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="userMapper">
<select id="findAll" resultType="cn.ahpu.domain.User">
select * from user
</select>
<insert id="save" parameterType="cn.ahpu.domain.User">
insert into user values(null,#{username},#{password},#{sex},#{address},#{birthday})
</insert>
<update id="update" parameterType="cn.ahpu.domain.User">
UPDATE USER
set username=#{username},password=#{password},sex=#{sex},address=#{address},birthday=#{birthday}
where id=#{id}
</update>
<delete id="delete" parameterType="java.lang.Integer">
DELETE FROM USER where id=#{jibenleixinghuluanxie}
</delete>
</mapper>
SqlMapConfig.xml 同上略
User.java同上略
UserDao.java
package cn.ahpu.dao;
import cn.ahpu.domain.User;
import java.util.List;
/**
* @author 寒面银枪
* @create 2020-01-07 16:33
*/
public interface UserDao {
/**
* 查询所有
* @return
*/
public List<User> findAll();
/**
* 保存用户
* @param user
*/
public void save(User user);
/**
* 更新用户
* @param user
*/
public void update(User user);
/**
* 根据id删除用户
* @param id
*/
public void del(Integer id);
}
UserDaoImpl.java (和整合后的ssh一样,传入一个sessionFactory)
package cn.ahpu.dao.impl;
import cn.ahpu.dao.UserDao;
import cn.ahpu.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import javax.swing.plaf.SliderUI;
import java.util.List;
/**
* @author 寒面银枪
* @create 2020-01-07 16:37
*/
public class UserDaoImpl implements UserDao {
//仔细回忆一下ssh整合后 dao必须的配置不就是个sessionFactory吗^_^ 哈哈哈 原理在此处
//工厂sessionFactory可以读取所有的配置文件 可以new出sqlSession
//所有的方法共有factory对象 (工厂一个就行了 sqlSession必须多例,由这唯一的一个工厂来创建多个session)
private SqlSessionFactory sessionFactory;
public UserDaoImpl(SqlSessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
//下面的每一个方法应该获取一个单独的sqlSession对象 工厂来给每个方法都创建一个就是了
//由于sqlSession线程不安全 用完就需要立即关闭
@Override
public List<User> findAll() {
SqlSession sqlSession = sessionFactory.openSession();
List<User> list = sqlSession.selectList("userMapper.findAll");
sqlSession.close();//一定要关闭 仅仅是一个方法级别的sqlSession 根据昨天的自定义框架知道,本质上关闭的是conn,pst,rs
return list;
}
@Override
public void save(User user) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.insert("userMapper.save",user);
sqlSession.commit();
sqlSession.close();
}
@Override
public void update(User user) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.update("userMapper.update",user);
sqlSession.commit();
sqlSession.close();
}
@Override
public void del(Integer id) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.delete("userMapper.delete",id);
sqlSession.commit();
sqlSession.close();
}
}
TestMybatisDao.java
package cn.ahpu;
import cn.ahpu.dao.UserDao;
import cn.ahpu.dao.impl.UserDaoImpl;
import cn.ahpu.domain.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* @author 寒面银枪
* @create 2020-01-07 17:06
*/
public class TestMybatisDao {
SqlSessionFactory sqlSessionFactory =null;//实际开发是单例的
@Before //每次执行test之前先执行before
public void init(){
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindAll(){
UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testSave(){
User user = new User(null, "tom", "tom", "男", "旧金山", new Date());
UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
userDao.save(user);
}
}
4.2 动态代理模式开发 (以后都用此★)
动态代理:不修改源码情况下对原有方法进行增强
仅仅只用提供sql语句和接口,即可访问数据库,再也不用写XXXdaoImpl实现类了
pom.xml 同上
SqlMapConfig.xml 同上
UserDao 同上
User 同上
UserMapper.xml 写法有变
动态代理模式必须遵守的2条规范
1. namespace:必须是对应接口的全限定类名(dao层执行此处sql的接口)
2. select/update/insert/delete 四个标签的id必须对应dao接口的方法名
<!--
动态代理模式必须遵守的规范
1. namespace:必须是对应接口的全限定类名(dao层执行此处sql的类)
2. select/update/insert/delete 四个标签的id必须对应dao接口的方法名
其他照旧写
-->
<mapper namespace="cn.ahpu.dao.UserDao">
<select id="findAll" resultType="cn.ahpu.domain.User">
SELECT * FROM USER
</select>
<insert id="save" parameterType="cn.ahpu.domain.User">
INSERT into USER VALUES (null,#{username},#{password},#{sex},#{address},#{birthday})
</insert>
</mapper>
TestMybatisProxy.java
public class TestMybatisProxy {
SqlSessionFactory sqlSessionFactory = null;
@Before
public void init(){
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindAll(){
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取dao接口的动态代理对象
//返回的是增强后的代理对象 注意我只提供了接口 没有实现类
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
sqlSession.close();
//竟然能直接打印出来 好像抽取BaseDao一样
//mybatis框架内部估计已经对基本的增删改查进行了抽取BaseDao 我们只用提供接口和sql语句即可
//这里的抽取肯定比hibernate强多了 因为我给了sql语句 你什么应该都能实现了
}
//测试保存
@Test
public void testSave(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = new User(null, "jerry", "jerry", "男", "北京", new Date());
userDao.save(user);
sqlSession.commit();//没有实现类了 需要自己提交
sqlSession.close();
}
}
动态代理小结:
好像抽取了BaseDao,但mybatis的动态代理肯定比hibernate强,我提供了sql语句,你什么都能封装了应该!
从今往后访问数据库提供sql语句和声明接口即可,只需要写:方法名,参数名,返回值类型具体实现完全不用管,简直不要太简单 (仔细想想之前自己还要写“长长的id”,有不报错,万一写错一个字母呢?肯定要帮你封装)
四、核心配置文件详解
配置文件中的标签和顺序
名称 | 含义 |
properties?, | 配置属性(学习) |
settings? | 全局配置:缓存,延迟加载(第四天学) |
typeAliases? | 类型别名(学习) |
typeHandlers? | 类型转换(操作)(了解) |
objectFactory? objectWrapperFactory? reflectorFactory? | 不用 |
plugins? | 插件:分页插件(ssm实战学) |
environments? | 环境配置(数据源) |
databaseIdProvider? | 数据库提供商 不管 不用 |
mappers? | 引入映射配置文件(学习) |
dtd约束
约束符号 | 约束含义 |
? | 一个或者零个 |
| | 任选其一 |
+ | 最少一个(1个或多个) |
* | 零个或多个 |
, | 必须按照此顺序编写 |
properties文件分离数据库4大核心属性配置
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatisdb_331
jdbc.username=root
jdbc.password=root
SqlMapConfig.xml
<configuration>
<!--<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatisdb_331"></property>
<property name="jdbc.username" value="root"></property>
<property name="jdbc.password" value="root"></property>
</properties>-->
<!--将四大基本配置独立出去 极大方便查看与修改数据库-->
<!--引入外部属性文件-->
<properties resource="jdbc.properties"></properties>
<!--
${jdbc.driver}:是ognl表达式
xml中没有el表达式
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
......
</configuration>
typeAliases 为类的全路径名取别名
(核心配置文件里取别名,mapper.xml映射文件里使用别名)
单类型映射:
SqlMapConfig.xml内取别名
<typeAliases>
<typeAlias type="cn.ahpu.domain.User" alias="user"></typeAlias>
</typeAliases>
UserMapper.xml
测试仍然可以运行
包的映射(今后的写法★)
(相当于为包内所有类取别名为简单类名(不区分大小写))
SqlMapConfig.xml
<typeAliases>
<!--包的映射:会将该包中所有的pojo类型全限定名取别名为简单类名 之后需要配置的别名就是简单类名
eg:相当于给cn.ahpu.domain.User取别名为User(user,USer都行 不区分大小写)
可以理解为引入了包内所有类,之后可以直接用包内的类的
以后都这么写★
-->
<package name="cn.ahpu.domain"></package>
</typeAliases>
UserMapper.xml
框架预定义别名:TypeAliasRegistry类(写出来,ctrl+左击可看)
public TypeAliasRegistry() {
registerAlias("string", String.class);
registerAlias("byte", Byte.class);
registerAlias("long", Long.class);
registerAlias("short", Short.class);
registerAlias("int", Integer.class);
registerAlias("integer", Integer.class);
registerAlias("double", Double.class);
registerAlias("float", Float.class);
registerAlias("boolean", Boolean.class);
registerAlias("byte[]", Byte[].class);
registerAlias("long[]", Long[].class);
registerAlias("short[]", Short[].class);
registerAlias("int[]", Integer[].class);
registerAlias("integer[]", Integer[].class);
registerAlias("double[]", Double[].class);
registerAlias("float[]", Float[].class);
registerAlias("boolean[]", Boolean[].class);
registerAlias("_byte", byte.class);
registerAlias("_long", long.class);
registerAlias("_short", short.class);
registerAlias("_int", int.class);
registerAlias("_integer", int.class);
registerAlias("_double", double.class);
registerAlias("_float", float.class);
registerAlias("_boolean", boolean.class);
registerAlias("_byte[]", byte[].class);
registerAlias("_long[]", long[].class);
registerAlias("_short[]", short[].class);
registerAlias("_int[]", int[].class);
registerAlias("_integer[]", int[].class);
registerAlias("_double[]", double[].class);
registerAlias("_float[]", float[].class);
registerAlias("_boolean[]", boolean[].class);
registerAlias("date", Date.class);
registerAlias("decimal", BigDecimal.class);
registerAlias("bigdecimal", BigDecimal.class);
registerAlias("biginteger", BigInteger.class);
registerAlias("object", Object.class);
registerAlias("date[]", Date[].class);
registerAlias("decimal[]", BigDecimal[].class);
registerAlias("bigdecimal[]", BigDecimal[].class);
registerAlias("biginteger[]", BigInteger[].class);
registerAlias("object[]", Object[].class);
registerAlias("map", Map.class);
registerAlias("hashmap", HashMap.class);
registerAlias("list", List.class);
registerAlias("arraylist", ArrayList.class);
registerAlias("collection", Collection.class);
registerAlias("iterator", Iterator.class);
registerAlias("ResultSet", ResultSet.class);
}
eg:以后java.lang.Integer直接写int即可
mappers不同引入方法
配置文件引入法
之前用的一直是这种方法
<mappers>
<!--配置文件引入法-->
<mapper resource="cn/ahpu/mapper/UserMapper.xml"/>
</mappers>
dao接口引入法:
<mappers>
<!--实体dao接口名引入法 注意引入的是执行sql的dao
前提: 必须在同一个包(包名一样即可)
文件名必须一致(仅后缀名不同)
-->
<mapper class="com.itheima.dao.UserDao"></mapper>
</mappers>
2个前提:
必须在同一个包(包名一样即可)
文件名必须一致(仅后缀名不同)
如下图:
直接引入包名(相当于引入包下所有类)(今后写法★★ 最简单)
UserMapper.xml配置文件更名为UserDao.xml
UserDao.xml
<mappers>
<!--引用一个包中所有dao接口-->
<package name="cn.ahpu.dao"></package>
</mappers>
也要满足上面引入dao接口的那两个前提
2个前提:
必须在同一个包(包名一样即可)
文件名必须一致(仅后缀名不同)
五、输入参数类型和输出参数类型
各种参数类型
- 输入参数
简单类型: 基本数据类型+ String类型
#{} :名称随便
${} : ${value}
pojo 类型
#{} : ${} : 属性名引用
包装对象类型
引用 #{属性.属性名} (类似el、ongl表达式 )
Map集合
引用: #{key}
多个参数 (前提都是简单参数 才能一次传入多个)
引用时:#{param1},#{param2}…#{paramN} - 返回值类型
主要处理列与属性名不一致: 不处理时查到的javabean对象对应的属性为null, 因此必须写映射配置
多条件查询:(其中的包装对象类型)
自定义新的javabean封装参数集合(麻烦 但适合团队协作开发)
public List<User> findByCondition(User user,Integer startIndex,Integer pageSize);
既有pojo 又有简单类型 mybatis不支持dao中方法的这种传参方式 #{}${}都没法写
解决方法:
新建javaBean 参数集封装成一个新的javaBean
QueryVO.java
package cn.ahpu.domain;
/**
* @author 寒面银枪
* @create 2020-01-07 21:51
*
* 存储参数值
*
*/
public class QueryVO {
private User user;
private Integer startIndex;
private Integer pageSize;
//...省略get/set
}
然后dao里可以写
UserDao.java
public List<User> findByQueryVO(QueryVO queryVO);
TestMybatisProxy.java
@Test
public void testFindByQueryVO(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//创建queryVO对象
QueryVO queryVO = new QueryVO();
User user = new User();
user.setUsername("小");
queryVO.setUser(user);
queryVO.setStartIndex(0);
queryVO.setPageSize(2);
List<User> list = userDao.findByQueryVO(queryVO);
for (User u : list) {
System.out.println(u);
}
sqlSession.close();
}
映射配置文件
UserDao.xml
<!--条件查询
domian包被核心xml引入了 因此domian包下的所有类都只用写类名即可 且不区分大小写
-->
<select id="findByQueryVO" parameterType="queryvo" resultType="user">
SELECT * FROM USER where username like "%"#{user.username}"%" limit #{startIndex},#{pageSize}
</select>
执行:TestMybatisProxy.testFindByQueryVO*
很明显自定义javabean过于麻烦
各种参数集合放到map中(简单 但不适合团队协作开发 个人开发就用这个吧)
TestMybatisProxy.java
@Test
public void testFindByMap(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//创建map对象
Map<String,Object> map=new HashMap<String,Object>();
map.put("username","小");
map.put("startIndex",0);
map.put("pageSize",2);
List<User> list = userDao.findByMap(map);
for (User u : list) {
System.out.println(u);
}
sqlSession.close();
}
UserDao.java
List<User> findByMap(Map<String, Object> map);
UserDao.xml
<!--条件查询
封装到简单map #{}内直接写map的key
注意换id为方法名
-->
<select id="findByMap" parameterType="map" resultType="user">
SELECT * FROM USER where username like "%"#{username}"%" limit #{startIndex},#{pageSize}
</select>
简单 但不适合团队协作开发,每个人写的key可能各不相同
观察发现前面写的所有dao的操作数据库的方法都只能传递单个参数(不然sql语句的参数不好拼 parameterType只能配置一个没法写),那是不是不可以传两个参数呢?其实不是,当多个参数都是简单类型时,可以一次传入多个参数的
TestMybatisProxy.java
@Test
public void testFindByManyParam(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//创建map对象
List<User> list = userDao.findByManyParam("小",0,2);
for (User u : list) {
System.out.println(u);
}
sqlSession.close();
}
UserDao.java
List<User> findByManyParam(String username, Integer startIndex, Integer pageSize);
UserDao.xml
同样注意id必须是方法名(用框架动态代理的前提)
<!-- 条件查询
当都是简单参数时,可以一次性传入多个
parameterType没必要写也没法子写了
引用时写法特殊固定:#{param1},#{param2}.....#{paramN}
-->
<select id="findByManyParam" resultType="user">
SELECT * FROM USER where username like "%"#{param1}"%" limit #{param2},#{param3}
</select>
返回值类型(处理表列名和javabean属性名不一致)
数据库表列名和javabean属性名不一致,写需要再写映射配置 就是和hibernate一样加上主键和普通属性的映射罢了,只不过前面属性名和列名一致时mybatis可以省略罢了
改两个列名: 主键id改成uid username改成uname
UserMapper.xml ★
<mapper namespace="cn.ahpu.dao.UserDao">
<!--resultMap结果集映射:一般用于处理列名和属性名不一致的情况
id="":唯一标识
type="":返回值类型
-->
<resultMap id="userList" type="user">
<!--id:一般写主键映射
property:属性名
column:列名
-->
<id property="id" column="uid"></id>
<!--映射普通属性和列-->
<result property="username" column="uname"></result>
</resultMap>
<!--由于列名与属性名不一致
resultType="user"已经不好使了 改写成:
resultMap="userList"
-->
<select id="findAll" resultMap="userList">
SELECT * FROM USER
</select>
</mapper>
其他代码都不变
TestMybatisProxy
@Test
public void testFindAll(){
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取dao接口的动态代理对象
//返回的是增强后的代理对象 注意我只提供了接口 没有实现类
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
sqlSession.close();
}
六、小结 (很碎 需要整理 可当做串线)
mybatis 第二天
mybatis crud
<insert id="" parameterType="">insert into ........</insert> sqlSession.insert("namespace.id", pojo)
<update id="" parameterType="">update 表 set.......</update> sqlSession.update("namespace.id", pojo);
<delete id="" parameterType="int">delete from 表 ........</delete> sqlSession.delete("namespace.id", id);
<select id="" parameterType="" resultType="返回值类型">
select * from 表 ........
</select>
sqlSession.selectList("namespace.id", 参数);
注意:
selectList :查询返回一个集合对象
selectOne 查询返回一个对象
${}: 直接拼接, 不会转换类型的, 不能防注入 , 当传入的简单类型, ${value}
#{}: 可以转换类型,可以防注入,相当于 ? ,当传入简单类型:#{随便写}
参数类型
简单类型:
pojo类型:${属性} #{属性}
复杂类型(包装类型): 一个pojo中有另一pojo的属性 ${属性} #{属性.属性}
Map集合:#{key}
多个参数: #{param1},#{param2} ........
传统模式:接口UserDao 实现类:UserDaoImpl , 映射配置文件
代理模式:接口UserDao 映射配置文件UserDao.xml
规范:namespace 必须接口的全限类名
配置的文件的路径必须与接口的包名路径一致
子标签(select,insert ,update ,delete) id 必须是接口的中的方法
参数类型必须与parameterType 是一致的
返回值类型必须与resultType 是一致的
核心配置文件
properties: 引入属性文件的
typeAliaes :别名映射 <package name="包名"> 则包下所有类全部取别名为简单类名,不区分大小写
mappers: 引入配置文件
resouce="xxxx/XXXMapper.xml"
class="cn.ahpu.mapper.XXXMapper"
url="file:///xxx.xml" 机器上的绝对路径,麻烦,不用
<package name="接口所在的包"> 相当于引入包下所有配置文件(或者说dao)
返回值类型
resultType="pojo类型" 列名与属性名一致
<resultMap id="" type="pojo">列名与属性名不一致
<id column ="" property=""/>
<result column ="" property="">
</resultMap>