参考链接: 在Java中使用_(下划线)作为变量名
mybatis第一天
1.mybatis概述和环境搭建
mybatis概述
mybatis环境搭建
1. 创建maven工程、添加开发依赖、创建数据库和表;
2. 创建domain实体类和dao
mybatis是一门java语言编写持久层框架,大大简化了jdbc操作,省去了我们注册驱动,获取连接等细节操作。
org.mybatis
mybatis
3.4.5
mysql
mysql-connector-java
8.0.11
junit
junit
4.11
test
log4j
log4j
1.2.12
3. 在resource中编写mybatis主配置文件
4. 编写每个dao接口的映射配置文件
/**
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
List<User> findAll();
}
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
default="mysql">
id="mysql">
type="jdbc">
type="pooled">
name="driver" value="com.mysql.jdbc.Driver"/>
name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
name="username" value="root"/>
name="password" value="78910J"/>
resource="com/itheima/dao/IUserDao.xml">
5.注意事项
6.测试类中测试方法编写
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
namespace="com.itheima.dao.IUserDao">//namespace:接口的路径 定位类中方法的具体位置
id="findAll" resultType="com.itheima.domain.User"> SELECT * FROM USER
1.在resource中创建IUserDao.xml时,文件的位置必须和IUserDao包结构相同,创建IUserDao.xml所在目录结
构时要一级一级创建。
2.映射配置文件中的mapper的namespace属性值必须是IUserDao的全类名
3.执行sql操作的配置id属性必须是执行方法的名词,例如 <select id="findAll"
@Test
public void testFindAll() throws IOException {
//1.读取SqlMapConfig.xml配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂类
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用SqlSessionFactory工厂创建SqlSession核心对象
/*SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射
关系经过编译后的内存镜像.SqlSessionFactory对象的实例可以通
过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder
则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory
的实例.每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心.
同时SqlSessionFactory也是线程安全的,SqlSessionFactory一旦被创建,应该在
应用执行期间都存在.在应用运行期间不要重复创建多次,建议使用单例模式.SqlSessionFactory
是创建SqlSession的工厂.*/
SqlSession session = factory.openSession();//openSession方法默认手动提交 填写false就是自动
提交 当对表数据crud就需要提交事务
//4.使用SqlSession创建接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.执行查询方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.释放资源
is.close();
session.close();
}2.mybatis注解开发和编写dao实体类方式
mybatis注解开发
编写dao实现类开发
1.在核心配置文件SqlMapConfig.xml的<mappers>中添加注解映射方式:
<mappers>
<mapper class="com.itheima.dao.IUserMapper"/>
mappers>
2.定义接口和抽象方法,在抽象方法上添加对应的注解:
public interface IUserMapper {
/**
* 查询所有用户信息
*/
@Select("select * from user")
public List<User> findList();
}
3.进行测试:
@Test
public void testFindList() throws IOException {
//1.读取核心配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂类
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.创建SqlSession核心对象
SqlSession session = factory.openSession();
//4.获取dao代理对象
IUserMapper mapper = session.getMapper(IUserMapper.class);
//5.执行查询操作
List<User> users = mapper.findList();
for (User user : users) {
System.out.println(user);
}
//6.释放资源
is.close();
session.close();
}
1.编写实现类:
public class UserDaoImpl implements IUserDao{
//1.声明SqlSessionFactory工厂类
private SqlSessionFactory factory;
//2.构造赋值
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public List<User> findAll() {注意:同一个dao接口不允许配置两种映射方式,例如:下列写法是错误的
3.自定义mybatis框架
流程分析
自定义mybatis流程分析.png
alt text
Alt text
alt text
新建module,根据入门案例测试方法创建缺少的接口和类
导入资料中utils目录中的XMLConfifigBuilder.java文件,并修改错误
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用查询的相关方法,哪个namespace中的哪个id方法对应的sql
List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");
//3.释放资源
session.close();
return users;
}
}
2.进行测试
@Test
public void testFindAllImpl() throws IOException {
//1.读取核心配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂类
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.创建实现类对象并调用实现类方法查询所有用户信息
UserDaoImpl dao=new UserDaoImpl(factory);
List<User> users = dao.findAll();
//4.遍历输出
for (User user : users) {
System.out.println(user);
}
//4.释放资源
is.close();
}
resource="com/itheima/dao/IUserDao.xml"/>
class="com.itheima.dao.IUserDao"/>
完成SqlSessionFactoryBuilder、SqlSessionFactory接口实现类、SqlSession接口实现类功能(实现类要自
己创建)
SqlSessionFactoryBuilder代码实现
1.添加依赖:
<dependency>
<groupId>dom4jgroupId>
<artifactId>dom4jartifactId>
<version>1.6.1version>
dependency>
<dependency>
<groupId>jaxengroupId>
<artifactId>jaxenartifactId>
<version>1.1.6version>
dependency>
2.创建Configuration和Mapper两个javabean对象
public class Configuration {
private String driver;
private String url;
private String username;
private String password;
private Map<String,Mapper> mappers=new HashMap<String, Mapper>();//保存多组映射信息的map集
合
// getter/setter方法省略
public void setMappers(Map<String, Mapper> mappers) {
this.mappers.putAll(mappers);
}
}
public class Mapper {
private String queryString;
private String resultType;
// getter/setter方法省略
}
/**
* 构建者对象
*/
public class SqlSessionFactoryBuilder {
/**
* 根据配置文件输入流对象创建工厂对象
* @param configStream 配置文件输入流
* @return
*/
public SqlSessionFactory build(InputStream configStream) {
//1.使用XMLConfigBuilder解析配置文件
Configuration configuration = XMLConfigBuilder.loadConfiguration(configStream);
System.out.println("configuration = " + configuration);
//2.创建工厂实现类对象并返回
return new DefaultSqlSessionFactory(configuration);DefaultSqlSessionFactory代码实现
DefaultSqlSession代码实现
}
}
/**
* SqlSessionFactory接口的实现类
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory {
//声明封装主配置文件对象
private Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration=configuration;
}
/**
* 生产操作数据库的核心SqlSession对象
* @return
*/
public SqlSession openSession() {
//创建SqlSession实现类对象并返回
return new DefaultSqlSession(configuration);
}
}
/**
* 操作数据库核心SqlSession接口的实现类
*/
public class DefaultSqlSession implements SqlSession {
//声明封装主配置文件对象,因为getMapper需要连接和映射信息,所以需要这个配置对象
private Configuration configuration;
private Connection conn;
public DefaultSqlSession(Configuration configuration) {
this.configuration=configuration;
//从连接池工具类中获取连接对象
conn= DataSourceUtils.getConnection(configuration);
}
/**
* 通过动态代理的方式创建接口的实现类对象
* @param daoClass 接口的Class对象
* @param 返回接口实现类对象
* @return
*/
public <T> T getMapper(Class<T> daoClass) {
//创建dao代理对象并返回
T t = (T) Proxy.newProxyInstance(daoClass.getClassLoader(),
new Class[]{daoClass},
new MapperProxy(configuration.getMappers(),conn));
return t;DataSourceUtils工具类获取连接
InvocationHandler实现类MapperProxy的代码实现
}
/**
* 释放资源
*/
public void close() {
try {
if (conn!=null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 将来封装连接池的工具类,目前不使用连接池
*/
public class DataSourceUtils {
public static Connection getConnection(Configuration cfg) {
//1.注册驱动
try {
Class.forName(cfg.getDriver());
//2.获取连接
return
DriverManager.getConnection(cfg.getUrl(),cfg.getUsername(),cfg.getPassword());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
/**
* 当dao代理对象的方法被调用时,该监听类的invoke方法就会执行
*/
public class MapperProxy implements InvocationHandler {
//map集合的key=全类名+方法名
private Map<String, Mapper> mappers;//封装了sql语句和结果类型
private Connection conn;//连接对象
public MapperProxy(Map<String, Mapper> mappers,Connection conn) {
this.mappers=mappers;
this.conn=conn;
}
//当dao代理对象的方法被调用时,invoke方法就会执行,参数method表示代理对象调用的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1.根据执行的method方法从mappers集合中找到对应的mapper对象
//1.1.获取方法名将MapperProxy中需要的Executor类从资料中复制到项目的utils包下,该Executor类的selectList方法帮
我们查询所有信息并封装到List中
注意:在没网的情况下,需要删除SqlMapConfifig和映射文件的约束信息;
mybatis第二天
1.mybatis的CRUD操作
1.1.映射配置文件IUserDao.xml信息
String methodName = method.getName();
//1.2.获取全类名
String className = method.getDeclaringClass().getName();
//1.3.拼接map集合的key,找到对应的mapper对象
String key=className+"."+methodName;
System.out.println("key = " + key);
//1.4.找到要的Mapper对象
Mapper mapper = mappers.get(key);
if (mapper==null) {
//没找到,配置的全类名有误或者方法有误
throw new IllegalStateException("在"+className+"类中没有"+methodName+"方法");
}
//2.调用Executor工具类的selectList方法执行查询操作
return new Executor().selectList(mapper,conn);
}
}
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
namespace="com.itheima.dao.IUserDao">
id="findAll" resultType="com.itheima.domain.User"> SELECT * from user
id="saveUser" parameterType="com.itheima.domain.User">
/*添加用户信息之后查询新用户的id keyProperty对应的是user的id属性*/
keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
select last_insert_id();
/*selectKey是后来加的,在添加用户信息时可以先忽略*/
insert into user values (null,#{username},#{birthday},#{sex},#{address})
id="updateUser" parameterType="com.itheima.domain.User">1.2.封装数据的User类省略
1.3.测试类代码
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
id="deleteUser" parameterType="Integer">
delete from user where id=#{id}
id="findById" resultType="com.itheima.domain.User" parameterType="int"> select * FROM user where id=#{id}
id="findByName" parameterType="String" resultType="com.itheima.domain.User"> select * from user where username like #{username}
id="findTotal" resultType="int"> select count(*) from user
public class MybatisTest {
private InputStream is;
private SqlSession session;
private IUserDao userDao;
/**
* 初始化mybatis
*/
@Before
public void init() throws IOException {
//1.加载核心配置文件SqlMapConfig.xml
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.创建核心SqlSession对象
session = factory.openSession();
//4.创建IUserDao对象
userDao = session.getMapper(IUserDao.class);
}
/**
* 测试查询所有用户信息的findAll()方法
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
//遍历打印
for (User user : users) {System.out.println(user);
}
}
/**
* 测试保存用户信息的saveUser()方法
*/
@Test
public void testSaveUser(){
//创建用户信息
User user=new User();
user.setUsername("老周");
user.setBirthday(new Date());
user.setAddress("武汉");
user.setSex("男");
System.out.println("添加前user = " + user);
//添加到数据
int row = userDao.saveUser(user);
System.out.println("影响的行数row = " + row);
//在IUserDao.xml配置了selectKey后,添加完user就会查询到新用户的id并封装到user的id属性上。
System.out.println("添加后user = " + user);
}
/**
* 测试更新用户信息的updateUser()方法
*/
@Test
public void testUpdateUser(){
//准备要修改用户的信息信息
User user=new User();
user.setId(52);
user.setUsername("老李");
user.setBirthday(new Date());
user.setAddress("孝感");
user.setSex("女");
//修改用户
int row = userDao.updateUser(user);
System.out.println("row = " + row);
}
/**
* 测试更加用户id删除用户信息的deleteUser()方法
*/
@Test
public void testDeleteUser(){
//根据id删除用户信息
int row = userDao.deleteUser(52);
System.out.println("row = " + row);
}
/**
* 测试根据id查询用户信息的findById()方法
*/
@Test
public void testFindById(){
User user = userDao.findById(50);
System.out.println(user);2.mybatis映射配置参数和返回值类型深入学习
2.1.parameterType传递pojo包装对象
QueryVo实体类
映射文件配置
}
/**
* 测试根据用户名称模糊查询的findByName()方法
*/
@Test
public void testFindByName(){
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
/**
* 测试查询总记录条数的findTotal()方法
*/
@Test
public void testFindTotal(){
int total = userDao.findTotal();
System.out.println("total = " + total);
}
/**
* 释放资源
*/
@After
public void destory() throws IOException {
//提交事务
session.commit();
//6.释放资源
session.close();
is.close();
}
}
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}测试类测试方法编写
mybatis的dao层开发模式
返回值类型-javabean的属性和表字段名一致情况(了解)
javabean实体类
id="findByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User"> /*username是user的属性,user是QueryVo的属性*/ select * from user where username like #{user.username}
/**
* 测试根据 QueryVo 中的条件查询用户的findByVo()方法
*/
@Test
public void testFindByVo(){
//创建QueryVo对象
QueryVo queryVo=new QueryVo();
//创建模糊查询条件封装到user对象中
User user=new User();
user.setUsername("%王%");
queryVo.setUser(user);
//执行查询
List<User> users = userDao.findByVo(queryVo);
//遍历打印
for (User u : users) {
System.out.println(u);
}
}
* 基于DAO代理方式(推荐使用)
* CRUD操作(保存操作|修改操作|删除操作|查询一个|模糊查询|单值查询|获取保存对象的id)
* 模糊查询需要注意
* 获取保存对象的id
* 输入参数 parameterType属性
* 输入参数的类型:int、string、User、plain old java object、包装类型ValueObject
* 输出参数 resultType属性、
* 输入参数的类型:User、int、string
* 解决实体类属性和数据库列名不对应
* 在sql语句上取别名, 对应, 简单
* 通过resultMap属性来映射java对象和数据库列名之间的关系
* <result property="userName" column="username">result>
property 遵循的是驼峰规则; column 单词下划线隔开解决办法1:sql的结果集使用别名,别名和javabean的属性一致
好处:查询效率高;弊端:书写麻烦,开发效率低。
解决办法2:使用mybatis给我们提供的配置结果集映射
好处:id="UMap"的可以重复使用,开发效率高;弊端:查询效率略低。
编写测试类测试方法
public class U {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
//自动生成setter、getter、toString省略,此时属性和表的字段名不一致
}
id="findAllU" resultType="com.itheima.domain.U"> select id userId,username userName,birthday userBirthday,sex userSex,address userAddress from user;
id="UMap" type="com.itheima.domain.U">
column="id" property="userId"/>
column="username" property="userName"/>
column="birthday" property="userBirthday"/>
column="sex" property="userSex"/>
column="address" property="userAddress"/>
id="findAllU" resultMap="UMap"> select * from user; 3.mybatis中编写dao实现类的使用(了解)
UserDaoImpl实现类代码
/**
* 测试使用别名,查询所有用户信息的findAllU()方法
*/
@Test
public void testFindAllU(){
List<U> us = userDao.findAllU();
//遍历打印
for (U u : us) {
System.out.println(u);
}
}
public class UserDaoImpl implements IUserDao {
private SqlSessionFactory factory;
//接收工厂对象,用于创建SqlSession对象
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public List<User> findAll() {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用selectList方法查询所有用户信息
List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");
//3.释放资源
session.close();
return users;
}
@Override
public int saveUser(User user) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用insert方法添加一条用户信息
int row = session.insert("com.itheima.dao.IUserDao.saveUser", user);
//3.提交并释放资源
session.commit();
session.close();
//返回影响的函数
return row;
}
@Override
public int updateUser(User user) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用update方法修改一条用户信息
int row = session.update("com.itheima.dao.IUserDao.updateUser", user);
//3.提交并释放资源session.commit();
session.close();
//返回影响的函数
return row;
}
@Override
public int deleteUser(int id) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用delete方法删除一条用户信息
int row = session.delete("com.itheima.dao.IUserDao.deleteUser", id);
//3.提交并释放资源
session.commit();
session.close();
//返回影响的函数
return row;
}
@Override
public User findById(Integer id) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用selectList方法查询所有用户信息
User user = session.selectOne("com.itheima.dao.IUserDao.findById",id);
//3.释放资源
session.close();
return user;
}
@Override
public List<User> findByName(String username) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用selectList方法根据username模糊查询所有用户信息
List<User> users = session.selectList("com.itheima.dao.IUserDao.findByName",username);
//3.释放资源
session.close();
return users;
}
@Override
public int findTotal() {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用delete方法删除一条用户信息
int total = session.selectOne("com.itheima.dao.IUserDao.findTotal");
//3.释放资源
session.close();
//返回总记录数
return total;
}
@Override
public List<User> findByVo(QueryVo vo) {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用selectList方法根据vo.user.username模糊查询所有用户信息修改测试类init方法和destory方法即可,其他测试方法都不需要改
4.mybatis中编写dao实现类的使用过程分析
5.properties标签、typeAliases标签、package标签使用
5.1.properties标签的作用
List<User> users =
session.selectList("com.itheima.dao.IUserDao.findByName",vo.getUser().getUsername());
//3.释放资源
session.close();
return users;
}
@Override
public List<U> findAllU() {
//1.创建核心的SqlSession对象
SqlSession session = factory.openSession();
//2.调用selectList方法查询所有用户信息
List<U> us = session.selectList("com.itheima.dao.IUserDao.findAllU");
//3.释放资源
session.close();
return us;
}
}
@Before
public void init() throws IOException {
//1.加载核心配置文件SqlMapConfig.xml
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
/*如果是使用dao代理方式,则需要创建SqlSession对象,并获取dao的代理对象*/
/*//3.创建核心SqlSession对象
session = factory.openSession();
//4.创建IUserDao对象
userDao = session.getMapper(IUserDao.class);*/
/*如果使用的是自定义dao实现类方法,则需要创建dao实现类对象,并传递factory工厂对象*/
userDao=new UserDaoImpl(factory);
}
@After
public void destory() throws IOException {
//提交事务,如果是自定义dao实现类就不需要,在实现类内部提交
//session.commit();
//6.释放资源,如果是自定义dao实现类就不需要,在实现类内部关闭
//session.close();
is.close();
}作用:将连接数据库的信息单独配置到一个properties属性文件中,配置方式如下
外部jdbcConfifig.properties配置文件
在SqlMapConfifig.xml跟标签下使用properties标签引入jdbcConfifig.properties
在dataSource中引入外部properties的各个属性
5.2.typeAliases标签、package标签使用作用
SqlMapConfifig.xml跟标签下使用typeAliases标签作用 :javabean取别名(了解)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=78910J
name="driver" value="com.mysql.jdbc.Driver"/>
name="url" value="jdbc:mysql://localhost:3306/mybatis?
serverTimezone=Asia/Shanghai"/>
name="username" value="root"/>
name="password" value="78910J"/>
或者
resource="jdbcConfig.properties">
或者
url="
file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.prop
erties">
type="pooled">
name="driver" value="${jdbc.driver}"/>
name="url" value="${jdbc.url}"/>
name="username" value="${jdbc.username}"/>
name="password" value="${jdbc.password}"/>
typeAliases标签下使用package标签作用 :指定包下的所有javabean的类名就是其别名,不区分大小写
(实用)
Mappers标签下使用package标签作用 :不用写mapper标签,resources或class指定包下所有dao对应的
映射文件都不用引入了,并且可以找到dao的接口或者dao接口对应的配置。(实用)
mybatis第三天
1.mybatis中连接池以及事务管理
1.1 mybatis连接池
mybatis中三种数据源介绍
在sqlMapConfifig.xml中配置
type="com.itheima.domain.User" alias="user"/>
name="com.itheima.dao"/>
UNPOOLED 不使用连接池的数据源,需要连接对象就使用DriverManager创建获取一个,使用完成就直接销毁
POOLED 使用连接池的数据源 (很常用)
JNDI 使用 JNDI 实现的数据源(最后讲解,了解)1.2 mybatis事务管理
mybatis中默认是开启也是,也就是增删改之后需要手动session.commit()方法手动提交事务;但是我们也可以设
置自动提交,在增删改完成之后不需要手动调用session.commit()提交事务。只需要在session =
factory.openSession(true);参数true表示自动提交。
2.mybatis中动态SQL
使用场景:如果条件存在就带条件查询,如果条件不存在就不带条件查询,适用于搜索等场景。
2.1 if标签 - 动态添加条件
在IUserDao.xml中配置查询语句
2.2 where 标签 - 代替where 1=1
在IUserDao.xml中修改之前配置的查询语句
在sqlMapConfig.xml中配置如下
type="pooled">
name="driver" value="${jdbc.driver}"/>
name="url" value="${jdbc.url}"/>
name="username" value="${jdbc.username}"/>
name="password" value="${jdbc.password}"/>
MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:
type="POOLED": MyBatis 会创建 PooledDataSource 实例
type="UNPOOLED": MyBatis 会创建 UnpooledDataSource 实例
type="JNDI": MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
id="findUserByCondition1" parameterType="user" resultType="user"> select * from user where 1=1 test="username!=null and username!=''">//连接判断条件不能为&&和|| and username = #{username} test="sex!=null"> and sex = #{sex} 2.3 foreach标签 - 遍历,适用于in的条件
foreach元素的属性主要有 item,index,collection,open,separator,close。
item: 循环体中的具体对象。支持属性的点路径访问,如 item.age,item.info.details。具体说明:在 list 和数
组中是其中的对象,在 map 中是 value,该参数为必选。(它是每一个元素进行迭代时的别名)
index:在 list 和数组中,index 是元素的序号;在 map 中,index 是元素的 key。
open :表示该语句以什么开始
separator :表示在每次进行迭代之间以什么符号作为分隔符
close :表示以什么结束
_parameter :不只是方法传递过来的参数可以被用来判断,取值
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数: 1.参数会被封装为一个map:_parameter就是代表这个map
2._parameter 可以get(0)得到第一个参数。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该
属性的值是不一样的,主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map
遍历map集合
id="findUserByCondition1" parameterType="user" resultType="user"> select * from user test="username!=null and username!=''"> and username = #{username} test="sex!=null"> and sex = #{sex} 需求:根据qv中list集合查询用户信息-
在IUserDao.xml中配置查询语句
测试类中测试- QueryVo中添加ids属性省略了
id="findByMap" parameterType="map" resultType="cn.itcast.mybatis.pojo.Product"> select * from user collection="_parameter" index="key" item="value" separator="and"> test="value !=null"> ${key} = #{value}
id="findUserByCondition2" parameterType="QueryVo" resultType="user"> select * from user test="ids!=null and ids.size>0"> id="findUserByCondition2" parameterType="QueryVo" resultType="user">
select * from user
test="ids!=null and ids.size>0">
and id in(
collection="ids" item="uid" separator=",">
#{uid}
)
@Test
public void testFindUserByCondition2(){
QueryVo qv=new QueryVo();
List<Integer> ids=new ArrayList<Integer>();
ids.add(41);2.4 补充1:抽取公共的sql语句
在IUserDao.xml中跟标签中使用sql标签定义公共sql语句
在中使用标签引入公共sql 3.mybatis多表之间关系 3.1 一对一关系 需求:一个账户只属于一个用户,查询账户信息的同时查询用户信息 实现步骤: 一对一映射 代码示例: 1.创建Account实体类以及IAccountDao接口 ids.add(45); ids.add(46); ids.add(48); qv.setIds(ids); List<User> list = userDao.findUserByCondition2(qv); //变量展示 for (User u : list) { System.out.println("u = " + u); } } id="selectTemplate"> select * from user id="findAll" resultType="com.itheima.domain.User">
refid="selectTemplate"/>
1.创建Account实体类以及IAccountDao接口
2.创建IAccountDao.xml映射问题
3.创建AccountDaoTest测试类进行测试
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//封装对应的user对象2.创建IAccountDao.xml映射文件
3.创建AccountTest测试类进行测试
private User user;
//setter、getter、toString方法省略
}
public interface IAccountDao {
/**
* 查询所有账号信息同时查询对应用户信息
* @return
*/
List<Account> findAll();
}
namespace="com.itheima.dao.IAccountDao">
id="accountUserMap" type="account">
column="aid" property="id"/>
column="uid" property="uid"/>
column="money" property="money"/>
property="user" javaType="user" column="uid">
column="id" property="id"/>
column="username" property="username"/>
column="birthday" property="birthday"/>
column="sex" property="sex"/>
column="address" property="address"/>
id="findAll" resultMap="accountUserMap"> /*注意:当多表查询结果有相同字段名时,我们需要取别名区分*/ SELECT u.*,a.id aid,a.UID,a.MONEY FROM user u,account a where u.id=a.UID;
@Test
public void testFindAll(){
//1.调用findAll方法
List<Account> list = accountDao.findAll();
//2.遍历打印结果
for (Account account : list) {
System.out.println(account);
}
}注意:当多表查询结果有相同字段名时,我们需要取别名区分
3.2 一对多关系
需求:一个用户有多个账户,查询用户信息的同时查询其所有账户信息
实现步骤
一对多映射
代码示例
在IUserDao中添加新的查询方法
在IUserDao.xml中重新配置查询语句
编写UserTest测试类进行测试
1.在user中添加List<Account> accounts属性,在IUserDao中添加新的查询方法
2.在IUserDao.xml中重新配置查询语句
3.在AccountDaoTest测试类进行测试
/**
* 多表查询:查询用户信息的同时查询其所有账户信息
* @return
*/
List<User> findAllUserAndAccount();
id="userAccountMap" type="user">
column="id" property="id"/>
column="username" property="username"/>
column="birthday" property="birthday"/>
column="sex" property="sex"/>
column="address" property="address"/>
property="accounts" javaType="java.util.List" ofType="account">
column="id" property="id"/>
column="uid" property="uid"/>
column="money" property="money"/>
id="findAllUserAndAccount" resultMap="userAccountMap"> SELECT * FROM user u LEFT OUTER JOIN account a ON u.id = a.UID; 3.3 多对多关系
3.3.1 需求1:查询角色信息以及该角色对应的所有用户信息
实现步骤
代码示例
1.创建实体类Role以及IRoleDao接口
/**
* 多表查询:查询用户信息的同时查询其所有账户信息
*/
@Test
public void testFindAllUserAndAccount(){
List<User> users = userDao.findAllUserAndAccount();
for (User user : users) {
System.out.println(user);
}
}
1.创建实体类Role以及IRoleDao接口
2.创建IRoleDao.xml映射文件,并配置查询信息
3.创建RoleDaoTest测试类,并测试查询方法
public class Role {
private Integer id;
private String roleName;
private String roleDesc;
//封装该角色对应的所有用户信息
private List<User> users;
//setter、getter、toString方法省略
}
public interface IRoleDao {2.创建IRoleDao.xml映射文件,并配置查询信息
3.创建RoleDaoTest测试类,并测试查询方法
3.3.2 需求2:查询用户信息以及该用户对应的所有角色信息
实现步骤
代码示例
/**
* 需求1:查询角色信息以及该角色对应的所有用户信息
*/
List<Role> findAll();
}
namespace="com.itheima.dao.IRoleDao">
id="roleMap" type="role">
column="rid" property="id"/>
column="ROLE_NAME" property="roleName"/>
column="ROLE_DESC" property="roleDesc"/>
property="users" javaType="java.util.List" ofType="user">
column="id" property="id"/>
column="username" property="username"/>
column="birthday" property="birthday"/>
column="sex" property="sex"/>
column="address" property="address"/>
id="findAll" resultMap="roleMap"> SELECT r.ID rid,r.ROLE_NAME,r.ROLE_DESC,u.* FROM role r LEFT JOIN user_role ur ON r.ID = ur.RID LEFT JOIN user u ON ur.UID = u.id
@Test
public void testFindAll(){
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println(role);
}
}
1.在实体类User中添加List<Role> roles属性,并在IUserDao中添加新的查询方法
2.在IUserDao.xml中重新配置查询语句
3.在UserDaoTest测试类进行测试1.在IUserDao中添加新的查询方法
2.在IUserDao.xml中重新配置查询语句
3.在UserDaoTest测试类进行测试
4.补充:JNDI
mybatis第四天
1.mybatis延迟加载
1.1 概念
/**
* 需求2:查询用户信息以及该用户对应的所有角色信息
*/
List<User> findAllUserAndRole();
id="userRoleMap" type="user">
column="id" property="id"/>
column="username" property="username"/>
column="birthday" property="birthday"/>
column="sex" property="sex"/>
column="address" property="address"/>
property="roles" javaType="java.util.List" ofType="role">
column="rid" property="id"/>
column="ROLE_NAME" property="roleName"/>
column="ROLE_DESC" property="roleDesc"/>
id="findAllUserAndRole" resultMap="userRoleMap"> SELECT u.*,r.ID rid,r.ROLE_NAME,r.ROLE_DESC FROM user u LEFT JOIN user_role ur ON u.id = ur.UID LEFT JOIN role r ON ur.RID = r.ID;
@Test
public void testFindAllUserAndRole(){
List<User> users = userDao.findAllUserAndRole();
for (User user : users) {
System.out.println(user);
}
}1.2 一对一实现延迟加载
1.2.1 在主配置文件SqlMapConfifig.xml中开启全局延迟加载
1.2.2 在映射配置文件IAccountDao.xml中配置延迟加载查询
1.2.3 在AccountDaoTest测试类中进行测试
1.3 一对多实现延迟加载
1.3.1 在映射配置文件IUserDao.xml中配置延迟加载查询
1.立即加载:只要一调用方法,不管用不用的到数据都立马去关联查询
2.延迟加载:只有再用到数据时才去关联查询,不用就不关联查询,好处:先从单表查询,需要时再从关联表去关联查
询,大大提高数据库性能;延迟加载也叫按需加载或懒加载
name="lazyLoadingEnabled" value="true"/>
name="aggressiveLazyLoading" value="false"/>
id="accountMap" type="account">
column="id" property="id"/>
column="uid" property="uid"/>
column="money" property="money"/>
property="user" javaType="user" column="uid"
select="com.itheima.dao.IUserDao.findById"/>
id="findAll" resultMap="accountMap"> select * FROM account
/**
* 延迟加载:查询所有账号信息同时查询对应用户信息
*/
@Test
public void testFindAll() {
List<Account> accounts = accountDao.findAll();
/*只要不调用和user相关的方法,就不会查关联表中的数据*/
for (Account account : accounts) {
System.out.println(account.getId()+","+account.getUid()+","+account.getMoney());
}
}1.3.2 在IAccountDao中添加fifindAccountById方法并在IAccountDao.xml配置
1.3.3 在UserDaoTest测试类中进行测试
2.mybatis中的一级缓存和二级缓存
2.1 缓存的概念
2.2 一级缓存
概念
id="userMap" type="user">
column="id" property="id"/>
column="username" property="username"/>
column="birthday" property="birthday"/>
column="sex" property="sex"/>
column="address" property="address"/>
property="accounts" ofType="account"
select="com.itheima.dao.IAccountDao.findAccountById" column="id"/>
id="findAll" resultMap="userMap"> SELECT * FROM USER ;
id="findAccountById" parameterType="int" resultType="account"> SELECT * FROM account where uid=#{uid};
@Test
public void testFindAll() {
List<User> list = userDao.findAll();
for (User u : list) {
System.out.println(u.getId()+","+u.getUsername()+","+u.getBirthday()+","+u.getSex()+","+u.getAd
dress());
/*只要不调用和account相关的方法,就不会查关联表中的数据*/
/*System.out.println(u.getAccounts());*/
}
}
存在内存中的临时数据就是缓存代码演示
结果说明
2.3 二级缓存
概念
代码演示
它指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们
提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有
的话直接拿出来用。当SqlSession对象消失时(close方法被调用),mybatis的一级缓存也就消失了。
@Test
public void testFirstLeverCache(){
User user1 = userDao.findById(43);
System.out.println("user1 = " + user1);
//测试一下关闭session
/*session.close();
session=factory.openSession(true);
userDao=session.getMapper(IUserDao.class);*/
//也可以清除缓存
//session.clearCache();
//再次执行相同的查询
User user2 = userDao.findById(43);
System.out.println("user2 = " + user2);
//判断user1和user2是不是同一个对象
System.out.println("user1==user2 : " + (user1==user2));
}
如果是同一个session对象,那么第二次查询的user对象和第一次查询的user对象是同一个user对象,最后打印的
结果是true,通过控制台日志可以看出只执行了一次查询;当中间关闭了session或者调用clearCache方法清除缓存之
后,那两个user对象就不是同一个对象了,控制台查看日志也会发现执行了两次查询。
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享
其缓存。
二级缓存的使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步:让当前的操作支持二级缓存(在select标签中配置)
@Test
public void testSecondLeverCache(){
//1.获取第一个sqlSession对象并查询user
SqlSession session1 = factory.openSession(true);
IUserDao userDao1 = session1.getMapper(IUserDao.class);
User user1 = userDao1.findById(43);结果说明以及注意事项
3.mybatis注解开发
3.1 mybatis注解开发CRUD操作
3.1.1 SqlMapConfifig核心配置文件环境搭建
System.out.println("user1 = " + user1);
//关闭session1
session1.close();
//2.获取第二个sqlSession对象并查询user
SqlSession session2 = factory.openSession(true);
IUserDao userDao2 = session2.getMapper(IUserDao.class);
User user2 = userDao2.findById(43);
System.out.println("user2 = " + user2);
session2.close();
//判断user1和user2是不是同一个对象
System.out.println("user1==user2 : " + (user1==user2));
}
两个对象虽然不是同一个对象,但是通过控制台发现只执行了一次查询
注意:一定要关闭之前的sqlSession对象
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
resource="jdbcConfig.properties"/>
name="com.itheima.domain"/>
default="mysql">
id="mysql">
type="jdbc">
type="pooled">
name="driver" value="${jdbc.driver}"/>
name="url" value="${jdbc.url}"/>
name="username" value="${jdbc.username}"/>
name="password" value="${jdbc.password}"/>
name="com.itheima.dao"/>
3.1.2 IUserDao中给方法添加注解
/**
* 查询所有操作
* @return
*/
@Select("select * from user")
List<User> findAll();
/**
* 保存用户
* @param user
* @return 影响数据库记录的行数
*/
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
//配置SelectKey将新添加用户的id封装到user中
@SelectKey(keyColumn = "id",keyProperty = "id",resultType =int.class,before = false, statement =
"select last_insert_id()")
int saveUser(User user);
/**
* 更新用户
* @param user
* @return 影响数据库记录的行数
*/
@Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}")
int updateUser(User user);
/**
* 根据 id 删除用户
* @param id
* @return 影响数据库记录的行数
*/
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
/**
* 根据 id 查询
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findById(Integer id);
/**
* 根据名称模糊查询
* @param username
* @return
*/
@Select("select * from user where username LIKE #{username};")
List<User> findByName(String username);
/**3.1.3 在测试类中测试
* 查询总记录条数
* @return 总记录条数
*/
@Select("select count(*) from user;")
int findTotal();
/**
* 根据 QueryVo 中的条件查询用户
* @param vo
* @return
*/
@Select(" select * from user where username like #{user.username}")
List<User> findByVo(QueryVo vo);
private InputStream is;
private SqlSession session;
private IUserDao userDao;
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
//1.获取主配置文件输入流
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂对象
factory = new SqlSessionFactoryBuilder().build(is);
//3.创建核心SqlSession对象
session = factory.openSession(true);
//4.获取IAccountDao代理对象
userDao = session.getMapper(IUserDao.class);
}
//查询所有操作
@Test
public void findAll(){
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
//保存用户
@Test
public void saveUser(){
//创建用户信息
User user=new User();
user.setUsername("老周");
user.setBirthday(new Date());
user.setAddress("武汉");
user.setSex("男");
System.out.println("添加前user = " + user);
//添加到数据
int row = userDao.saveUser(user);
System.out.println("影响的行数row = " + row);System.out.println("添加后user = " + user);
}
//更新用户
@Test
public void updateUser(){
//准备要修改用户的信息信息
User user=new User();
user.setId(55);
user.setUsername("老李");
user.setBirthday(new Date());
user.setAddress("孝感");
user.setSex("女");
//修改用户
int row = userDao.updateUser(user);
System.out.println("row = " + row);
}
//根据 id 删除用户
@Test
public void deleteUser(){
//根据id删除用户信息
int row = userDao.deleteUser(55);
System.out.println("row = " + row);
}
//根据 id 查询
@Test
public void findById(){
User user = userDao.findById(50);
System.out.println(user);
}
//根据名称模糊查询
@Test
public void findByName(){
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
//查询总记录条数
@Test
public void findTotal(){
int total = userDao.findTotal();
System.out.println("total = " + total);
}
//根据 QueryVo 中的条件查询用户
@Test
public void findByVo(){
//创建QueryVo对象
QueryVo queryVo=new QueryVo();
//创建模糊查询条件封装到user对象中
User user=new User();
user.setUsername("%王%");
queryVo.setUser(user);
//执行查询3.2 mybatis注解开发实例类属性与表列名不一致
3.2.1 IUserDao中给方法添加注解
3.2.2 在测试类中测试
3.3 mybatis注解开发一对一/多查询
3.3.1 IUserDao中给方法添加注解
List<User> users = userDao.findByVo(queryVo);
//遍历打印
for (User u : users) {
System.out.println(u);
}
}
@After
public void destroy() throws IOException {
session.close();
is.close();
}
/**
* 使用别名,查询所有用户信息;
* @return 所有用户信息
*/
@Select("select * from user")
//id="uMap"表示结果集映射的id,将来可以给其他@ResultMap复用
@Results(id="uMap",value = {
//id=true表示是主键,默认值是false
@Result(id=true,column = "id",property = "userId"),
@Result(id=false,column = "username",property = "userName"),
@Result(column = "birthday",property = "userBirthday"),
@Result(column = "sex",property = "userSex"),
@Result(column = "address",property = "userAddress")
}
)
List<U> findAllU();
@Test
public void findAllU(){
List<U> us = userDao.findAllU();
//遍历打印
for (U u : us) {
System.out.println(u);
}
}
/**3.3.2 IAccountDao中创建fifindAccountById方法并添加注解
3.3.3 在测试类中测试
* 立即查询:查询账户信息的同时查询其用户信息
* @return
*/
@Select("select * from account")
@Results(id="accountMap",value ={
@Result(id = true,column = "id",property = "id"),
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(column = "uid",property = "user",one = @One(
select="com.itheima.dao.IUserDao.findById",
fetchType = FetchType.EAGER//立即查询
)),
})
List<Account> findAllAccountAndUser();
/**
* 延时查询:查询用户信息的同时查询其所有账户信息
*/
@Select("select * from user")
@Results(id="userMap",value = {
@Result(id=true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "birthday",property = "birthday"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address"),
@Result(column = "id",property = "accounts",many = @Many(
select="com.itheima.dao.IAccountDao.findAccountById",
fetchType = FetchType.LAZY//延时查询
)),
})
List<User> findAllUserAndAccount();
public interface IAccountDao {
/**
* 根据uid查询对应的所有账户信息
* @param uid
* @return
*/
@Select("select * from account where uid=#{uid}")
List<Account> findAccountById(int uid);
}
//立即查询:查询账户信息的同时查询其用户信息
@Test
public void findAllAccountAndUser(){
List<Account> accounts = userDao.findAllAccountAndUser();
//变量打印3.4 mybatis注解开发使用二级缓存
3.4.1 在被测试的dao类上添加注解开启二级缓存即可
注意:SqlMapConfifig.xml中的中的
cacheEnabled默认值就是true,可以不用配置。
3.4.2 代码测试
mybatis扩展内容
for (Account account : accounts) {
System.out.println(account.getId()+"-"+account.getUid()+"-"+account.getMoney());
System.out.println(account.getUser());
}
}
//延时查询:查询用户信息的同时查询其所有账户信息
@Test
public void findAllUserAndAccount(){
List<User> users = userDao.findAllUserAndAccount();
for (User u : users) {
System.out.println(u.getId()+"-"+u.getUsername()+"-"+u.getBirthday()+"-"+u.getSex()+"-
"+u.getAddress());
// System.out.println(u.getAccounts());
}
}
//该接口查询开启二级缓存
@CacheNamespace(blocking = true)
public interface IUserDao {}
//测试二级缓存
@Test
public void testSecondLeverCache(){
//1.获取第一个sqlSession对象并查询user
SqlSession session1 = factory.openSession(true);
IUserDao userDao1 = session1.getMapper(IUserDao.class);
User user1 = userDao1.findById(43);
System.out.println("user1 = " + user1);
//关闭session1
session1.close();
//2.获取第二个sqlSession对象并查询user
SqlSession session2 = factory.openSession(true);
IUserDao userDao2 = session2.getMapper(IUserDao.class);
User user2 = userDao2.findById(43);
System.out.println("user2 = " + user2);
session2.close();
//判断user1和user2是不是同一个对象
System.out.println("user1==user2 : " + (user1==user2));
}1.mybatis使用第三方连接池
1.1 mybatis中连接池原理
1.2 使用第三方连接池步骤
1.2.1 自定义工厂类实现mybatis的DataSourceFactory接口
MyBatis 在初始化时,根据<dataSource>的 type 属性来创建相应类型的的数据源 DataSource,即:
type="POOLED": MyBatis 会创建 PooledDataSource 实例
type="UNPOOLED": MyBatis 会创建 UnpooledDataSource 实例
type="JNDI": MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
当我们在<dataSource type="POOLED">配置POOLED时mybatis就会为我们创建PooledDataSource对象,这个对象是
通过连接池工程创建出来的:
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}
}
public class UnpooledDataSourceFactory implements DataSourceFactory {
//代码省略
}
public interface DataSourceFactory {
void setProperties(Properties props);
DataSource getDataSource();
}
mybatis创建PooledDataSourceFactory工厂对象的同时会创建一个PooledDataSource连接池对象,然后调用工
厂对象的setProperties(Properties props)方法将SqlMapConfig.xml中的连接池配置信息通过props传递进来,当
进行CRUD操作时就调用getDataSource()方法获取连接池对象。
也就是说要想让mybatis使用第三方连接池,我们就得自己定义一个工厂类,在工厂来中创建第三方连接池对象并
在setProperties(Properties props)方法中设置连接参数,在getDataSource()方法中返回连接池对象
package com.itheima.factory;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.DataSourceFactory;
import javax.sql.DataSource;
import java.util.Properties;
//DruidDataSourceFactory不是alibaba的DruidDataSourceFactory
public class DruidDataSourceFactory implements DataSourceFactory {
//声明连接池对象
private DruidDataSource dataSource;
public DruidDataSourceFactory() {
//创建连接池对象
this.dataSource = new DruidDataSource();
}
@Override
public void setProperties(Properties props) {
//将SqlMapConfig.xml中的连接池配置信息设置给druid连接池对象
dataSource.setDriverClassName(props.getProperty("driver"));1.2.2 在SqlMapConfifig.xml中使用第三方连接池
1.2.3 在测试类中进行测试
dataSource.setUrl(props.getProperty("url"));
dataSource.setUsername(props.getProperty("username"));
dataSource.setPassword(props.getProperty("password"));
}
@Override
public DataSource getDataSource() {
return dataSource;
}
}
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
resource="jdbcConfig.properties"/>
name="com.itheima.domain"/>
default="mysql">
id="mysql">
type="jdbc">
type="com.itheima.factory.DruidDataSourceFactory">
name="driver" value="${jdbc.driver}"/>
name="url" value="${jdbc.url}"/>
name="username" value="${jdbc.username}"/>
name="password" value="${jdbc.password}"/>
name="com.itheima.dao"/>
2.mybatis查询传递其他类型参数
2.1 参数是Map集合
在IUserDao.xml中配置查询信息
在测试类中测试
//查询所有操作
@Test
public void findAll(){
//获取连接池对象的名称
DataSource dataSource = session.getConfiguration().getEnvironment().getDataSource();
System.out.println("dataSource = " + dataSource.getClass());//dataSource = class
com.alibaba.druid.pool.DruidDataSource
//查询所有用户信息
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
id="findUserByMap" resultType="user"> select * from USER test="username!=null and username!=''"> and username like #{username} test="sex!=null and username!=''"> and sex = #{sex}
//动态sql:根据map集合中的条件,查询用户信息
@Test
public void testFindUserByMap(){
//创建Map集合并封装查询参数
Map<String,Object> map=new HashMap<String,Object>();
map.put("username","%王%");
map.put("sex","女");
//查询符合条件的用户信息
List<User> users = userDao.findUserByMap(map);
for (User user : users) {
System.out.println(user);
}
}结论:使用map集合或者javabean对象作为参数,其实是一样的,map集合对应的就是javabean的属性。
2.2 参数是List集合
在IUserDao.xml中配置查询信息
在测试类中测试
结论:mybatis其实是将参数list集合先存到map中,key为list(即map.pust("list",list集合对象)),所以
collection="list"中的属性值必须是list,就相当于从map中取出list遍历
2.3 参数是数组- 和参数是list几乎一样
在IUserDao.xml中配置查询信息
id="findUserByList" resultType="user"> SELECT * FROM USER and id in( collection="list" item="id" separator=","> #{id} )
//动态sql:查询list集合中指定id的user信息
@Test
public void testFindUserByList(){
//创建list集合并存储要查的用户id
List<Integer> ids=new ArrayList<Integer>();
ids.add(41);
ids.add(43);
ids.add(48);
ids.add(50);
//查询符合条件的用户信息
List<User> users = userDao.findUserByList(ids);
for (User user : users) {
System.out.println(user);
}
}在测试类中测试
结论:查询参数是Array与查询参数是list集合的原理是一样的,都是现将对象存到map集合中,只不过参数
为Array时,存到map集合中的key叫array,所以collection="array"的值必须是array
2.4 多个参数情况以及@Param注解
在IUserDao中定义查询方法
在IUserDao.xml中配置查询信息
id="findUserByArray" resultType="user"> SELECT * FROM USER and id in( collection="array" item="id" separator=","> #{id} )
//动态sql:查询数组中指定id的user信息
@Test
public void testFindUserByArray(){
//创建list集合并存储要查的用户id
Integer[] ids={41,43,48,50};
//查询符合条件的用户信息
List<User> users = userDao.findUserByArray(ids);
for (User user : users) {
System.out.println(user);
}
}
/**
* 多个参数:根据用户名和性别查询用户信息
* @Param("username") :定义参数的别名,将来在映射文件中使用
*/
public List<User> findUserByUsernameAndSex(@Param("username") String username,@Param("sex")
String sex);
}
id="findUserByUsernameAndSex" resultType="user"> SELECT * FROM USER where username like #{username} and sex= #{sex} 在测试类中测试
结论:最好是结果@Param注解一起使用,映射文件中#{username}使用的变量名就是 @Param("username")注解的参数值 3.mybatis注解开发-动态sql 3.1 方式1:在select注解中添加script脚本 在在IUserMapper方法上定义注解 测试类测试 /** * 多个参数:根据用户名和性别查询用户信息 */ @Test public void testFindUserByUsernameAndSex(){ List<User> users = userDao.findUserByUsernameAndSex("%王%", "女"); for (User user : users) { System.out.println(user); } } /** * 动态sql:查询list集合中指定id的user信息 */ @Select({""}) public List<User> findUserByList(List<Integer> ids); //动态sql:查询list集合中指定id的user信息 @Test public void testFindUserByList(){ //创建list集合并存储要查的用户id List<Integer> ids=new ArrayList<Integer>(); ids.add(41); ids.add(43); ids.add(48); ids.add(50);总结:其实就是将xml映射文件中的配置拿过来用了,也是支持的。适用于带in的查询 3.1 方式2:字符串拼接(了解) 定义sql提供者UserMapperProvider类 在IUserMapper方法上定义注解 测试类测试 //查询符合条件的用户信息 List<User> users = userMapper.findUserByList(ids); for (User user : users) { System.out.println(user); } } /** * 为注解开发动态sql查询提供sql */ public class UserMapperProvider { /** * 动态sql:根据map集合中的条件,查询用户信息 * @param map 查询条件 * @return 根据条件返回sql */ public String findUserByMap(Map<String,Object> map){ StringBuilder sb=new StringBuilder("select * from user where 1=1 "); if(map.get("username")!=null){ sb.append(" and username like #{username}"); } if(map.get("sex")!=null){ sb.append(" and sex = #{sex}"); } return sb.toString(); } } public interface IUserMapper { /** * 动态sql:根据map集合中的条件,查询用户信息 */ @SelectProvider(type=UserMapperProvider.class,method = "findUserByMap") public List<User> findUserByMap(Map<String,Object> map); }3.2 方式3:使用mybatis中提供的SQL对象动态构建sql语句 修改UserMapperProvider提供者中的fifindUserByMap方法 4.mybatis使用Redis做二级缓存 总结 使用xml配置完成CURD操作 环境 jar包坐标 //动态sql:根据map集合中的条件,查询用户信息 @Test public void testFindUserByMap(){ //创建Map集合并封装查询参数 Map<String,Object> map=new HashMap<String,Object>(); map.put("username","%王%"); map.put("sex","女"); //查询符合条件的用户信息 List<User> users = userMapper.findUserByMap(map); for (User user : users) { System.out.println(user); } } public String findUserByMap(Map<String,Object> map){ return new SQL(){ //静态代码块 { SELECT("*"); FROM("user"); if (map.get("username")!=null) { WHERE("username like #{username}"); } if (map.get("sex")!=null) { AND(); WHERE("sex = #{sex}"); } } }.toString(); } 配置文件 单表查询 org.mybatis mybatis 3.4.5 mysql mysql-connector-java 5.1.38 junit junit 4.10 log4j log4j 1.2.12 测试多表查询 一对多 多表查询 多对多 使用annotation完成CURD操作 环境 与xml相同 单表查询多表查询 一对多