[转载] mybatis

参考链接: 在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相同 单表查询多表查询 一对多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设置了li(float:right),里面的li反过来显示 - 解决办法

设置了li(float:right),里面的li反过来显示 - 解决办法 可以让ul float:right ul里的li 依然float:left 本文转自许琴 51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/xuqin/1127540&#xff0c;如需转载请自行联系原作者

[转载] 纯函数和函数柯里化

参考链接&#xff1a; 用示例编写Java柯里化Currying函数 文章目录 纯函数什么是纯函数纯函数例子非纯函数例子 函数柯里化函数柯里化简单例子参数复用 纯函数 什么是纯函数 如果函数的调用参数相同&#xff0c;则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状…

[转载] scala

参考链接&#xff1a; 在Java的数字中使用下划线 1 scala 底层是有一种隐式转换机制&#xff0c;比如对String类型&#xff0c;底层会转化Scala的StringOps类型 2 scala 的通用的化简规则&#xff1a;调方法时候&#xff0c;方法的参数列表只有一个&#xff0c;则方法的&…

MySQL数据库学习笔记

MySQL常用语法总结 一.创建Web数据库 1.登陆到数据库 mysql -h hostname -u username -p mysql -h hostname -u username -D dbname -p 2.创建数据库 CREATE database dbname 3.使用数据库 USE dbname 4.创建数据库表 CREATE TABLE tablename (columns) 5.列的数据 create tabl…

[转载] java实现四种常用排序算法

参考链接&#xff1a; 用Java排序 四种常用排序算法 ##注&#xff1a;从小到大排 ##冒泡排序## 特点&#xff1a;效率低&#xff0c;实现简单 思想&#xff1a;每一趟将待排序序列中最大元素移到最后&#xff0c;剩下的为新的待排序序列&#xff0c;重复上述步骤直到排完所…

[转载] Java复制对象与集合工具类

参考链接&#xff1a; Java中的类和对象 项目中经常需要将某个对象的属性值复制给另一个对象&#xff0c;或者将一个集合复制到另一个集合。利用spring提供的BeanUtils&#xff0c;自己简单封装了一个工具类。 public class CopyUtils { /** * 复制集合 */ public static &l…

.NET深入学习笔记(4):深拷贝与浅拷贝(Deep Copy and Shallow Copy)

今天继续利用准备WSE安全开发文章的空闲时间&#xff0c;完善《.NET深入学习笔记》系列&#xff08;基本都是.Net重要的知识点&#xff0c;我都做了详细的总结&#xff0c;是什么、为什么、和怎么实现&#xff09;。想必很多人也接触过这两个概念。做过C的人对深浅拷贝的概念一…

VIM一般模式操作

2019独角兽企业重金招聘Python工程师标准>>> vim介绍 vim和vi几乎是一样的&#xff0c;唯一的区别就是当编辑一个文本时&#xff0c;使用vi不会显示颜色&#xff0c;而使用vim会显示颜色。 vim有三个模式&#xff1a;一般模式&#xff0c;编辑模式&#xff0c;命令模…

[转载] 解析Java的JNI编程中的对象引用与内存泄漏问题

参考链接&#xff1a; Java对象如何存储在内存中 JNI&#xff0c;Java Native Interface&#xff0c;是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code&#xff1b;在 native code 中嵌入 Java 虚拟机调用 Java 的…

[转载] java中创建对象的方式

参考链接&#xff1a; 用Java创建对象的不同方法 java中的4种创建对象的方式&#xff1a; 在这片博文中和大家简单分享一下常见的几种创建java对象的方式 1.使用 new 的方式&#xff0c;这也是我们最常见的一种方式 我们以 Person 类来举例说明 例&#xff1a; Person p…

Exchange 2007 SP1 如何定时清理日志???

Exchange 2007 SP1 如何定时清理日志&#xff1f;&#xff1f;&#xff1f; 时间:2011-12-31 11:00Tag标签&#xff1a;来源:未知 作者:达思科技 点击: 93次此文章出自&#xff1a; 专业数据恢复 问&#xff1a;Exchange 2007 SP1 如何定时清理日志&#xff1f;&#xff1f;&am…

[转载] java-继承和多态

参考链接&#xff1a; Java中的继承 继承&#xff1a; 继承就是保持已有类的特性而构造新类的过程。继承后&#xff0c;子类能够利用父类中定义的变量和方法&#xff0c;就像它们属于子类本身一样。 单继承&#xff1a;在类层次中&#xff0c;子类只继承一个父类的数据结构…

走进SQL Server 2005:备份与恢复功能

每当有任何新的软件发布的时候&#xff0c;你通常都会发现一些你从来不知道或者从来不知道你需要的新的特性。SQL Server 2000中存在的许多的备份和恢复特性都同样保留在了SQL Server 2005中&#xff0c;但是有一些新的提高同样值得你的关注。 镜像备份 SQL Server 2005让你可以…

[转载] Java对返回值的封装

参考链接&#xff1a; 用Java封装 定义自己所需要的返回值类型 public class CodeMsg implements Cloneable { private int retCode; private String message; // 通用异常 public static CodeMsg SUCCESS new CodeMsg(0, "success"); public static CodeMsg EMP…

stateful set 学习笔记

2019独角兽企业重金招聘Python工程师标准>>> 1、创建pv # cat pv.yaml kind: PersistentVolume apiVersion: v1 metadata:name: task-pv-volumelabels:type: local spec:capacity:storage: 3GiaccessModes:- ReadWriteOncehostPath:path: "/tmp/data" 2、…

[转载] Java中对象数组的使用

参考链接&#xff1a; 如何在Java中交换或交换对象 Java对象数组使用 一、Java数组的使用二、Java的对象数组2.1 问题提出2.2 问题解析2.3 问题拆分2.4 代码实现 一、Java数组的使用 对象数组其实和Java的数组类似的&#xff0c;所以要很清楚Java的数组是如何使用的&#xf…

Python自动化开发学习13-联合唯一

联合唯一 联合唯一&#xff0c;就是一个表中的多个字段的组合需要唯一。 使用mysql语句创建 比如创建一张hosts表&#xff0c;记录登录的ip地址或者hostname&#xff08;表中对应字段host&#xff09;和 端口号&#xff08;表中对应字段port&#xff09;&#xff0c;要求host 和…

[转载] Java获取泛型T的类型 T.class

参考链接&#xff1a; Java中的抽象 import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class Main{ public static void main(String[] args) { Foo<String> foo new Foo<String>(){}; // 在类的外部这样获取 Type type ((…

自定义控件---重写Listbox实现item图标变换和item点击事件

博客开通有一阵了&#xff0c;就是没有时间写&#xff0c;遗憾啊。&#xff01; 这几天做了个排序的自定义控件&#xff0c;在listbox item里放是button 并支持图标的交替变换 效果如下&#xff1a; 把代码贴上&#xff1a;1using System; 2using System.Collections.…

[转载] Spring面试题整理

参考链接&#xff1a; Java中的动态方法Dispatch和运行时多态 Spring面试题整理 2018年03月07日 21:11:46 hrbeuwhw 阅读数&#xff1a;49116 Spring 概述 1. 什么是spring? spring 是个Java企业级应用的开源开发框架。Spring主要用来开发Java应用&#xff0c;但是有…