mybatis框架--学习笔记(上)

使用JDBC操作数据库的问题总结:

(1)数据库连接,使用时创建,不使用时立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

设想:使用数据库连接池管理数据库连接。

(2)将sql语句硬编译到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护。

设想:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。

(3)向preoaredStatement中设置参数,对占位符号位置和设置参数值,硬编译在java代码中,不利于系统维护。

设想:将sql语句和占位符号和参数全部配置在xml中。

(4)从resultSet中遍历集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护

设想:向查询的结果集,自动映射成java对象。


1、mybatis入门程序:

mybatis框架--学习笔记(上)_第1张图片

(1)第一步:导入jar包。mybatis核心jar包,lib依赖包,数据库驱动包。

(2)第二步:配置SqlMapConfig.xml文件:配置mybatis的运行环境,数据源,事务等。




	
	
	
	
		
			
			
			
			
				
				
				
				
			
		
	
	

db.properties文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis_01
jdbc.username=root
jdbc.password=admin

(3)第三步:根据用户id(主键)查询用户信息

public class User {
	private int id;
	private String username;
	private String sex;
	private Date birthday;
	private String address;
        
        //下面省略get和set方法
}

映射文件(User.xml)






	
	
	
	
	
	
	 
		
	
	
	
	
	
	
		
		
		
			SELECT LAST_INSERT_ID()
		
		
	
		
		
	
		
		INSERT INTO USER(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
	
	
	
	
		DELETE FROM USER WHERE id=#{id}
	
	
	
	
	
		UPDATE USER SET username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} WHERE id=#{id}
	
	

(4)第四步:在SqlMapConfig.xml中加载映射文件


	
	
(5)第五步:编写程序:
public class MybatisFirst {
	
	//根据id得到一条用户记录
	@Test
	public void findUserById() throws IOException{
		//mybits配置文件
		String resource="SqlMapConfig.xml";
		//得到配置文件流
		InputStream inputStream=Resources.getResourceAsStream(resource);
		//创建会话工厂
		SqlSessionFactory sqlSessionFactory=
				new SqlSessionFactoryBuilder().build(inputStream);
		//通过会话工厂得到SqlSession
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		//通过SqlSession操作数据库
		//第一个参数:映射文件中statement的id,等于namespace+"."+statement的id
		//第二个参数:指定和映射文件中所匹配的parameterType类型的参数
		User user=sqlSession.selectOne("test.findUserById", 1);
		
		System.out.println(user);
		//释放资源
		sqlSession.close();
	}
	
	//根据用户名模糊查询
	@Test
	public void findUserByName() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory=
				new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		//List list=sqlSession.selectList("test.findUserByName", "%先生%");
		List list=sqlSession.selectList("test.findUserByName", "先生");
		for(User user:list)
		{
			System.out.println(user.getId()+user.getUsername());
		}
		sqlSession.close();
	}
	
	//插入用户
	@Test
	public void insertUser() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory=
				new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		User user=new User();
		user.setUsername("张同学");
		user.setBirthday(new Date());
		user.setSex("男");
		user.setAddress("汕头");
		
		sqlSession.insert("test.insertUser",user);
		
		//事务提交
		sqlSession.commit();
		System.out.println(user.getId());
		//打印插入后的user用户的id
		sqlSession.close();
		}
	
	//根据用户id删除用户
	@Test
	public void deleteUser() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory=
				new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		sqlSession.delete("test.deleteUser",6);
		
		sqlSession.commit();
		sqlSession.close();
		}
	
	//根据id修改用户
	@Test
	public void updateUser() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory=
				new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		User user=new User();
		user.setId(10);//id必须存在
		user.setUsername("修改后的张同学");
		user.setBirthday(new Date());
		user.setSex("男");
		user.setAddress("汕头");
		sqlSession.update("test.updateUser",user);
		
		sqlSession.commit();
		sqlSession.close();
		}
}

小结:

(1)parameterType:在映射文件中通过parameterType指定输入参数的类型

(2)resultType:在映射文件中通过resultType指定输出结果类型

(3)#{}和${}

#{}表示一个占位符号,参数可以是简单类型。参数是简单类型是时,命名无要求,可以是value或者其他值

${}表示一个拼接符号,会引入sql注入,所以不建议使用,参数可以是简单类型。参数是简单类型是时,命名只能是value。

(4)selectOne和selectList

--selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现,使用selectList也可以实现(List集合中只有一个对象)

--selectList表示查询出一个列表(多条记录)进行映射,如果使用selectList查询可以实现,不可以使用selectOne实现。


2、mybatis和hibernate本质区别和应用场景:

Hibernate:是一个标准的ORM框架(对象关系映射),不需要程序员写sql,sql语句自动生成了。对sql语句进行优化、修改比较困难

应用场景:使用于需求与变化不多的中小型项目,

Mybatis:专注于sql本身,需要程序员自己编写sql语句,修改比较方便。Mybatis是一个不完全的ORM框架,虽然需要程序员自己编写sql,mybatis也可以实现映射(输入映射,输入映射)

应用场景:使用于需求变化较多的项目,比如:互联网项目。

3、SqlSession:

SqlSession是一个面向用户的接口,线程不安去,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。SqlSession最佳应用场合是在方法体内,定义成员局部变量使用。


4、原始dao开发方法:(程序员自己写daodao接口实现类)

(1)写dao接口和dao接口实现类:

(2)需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession。

//Dao接口
public interface UserDao {
	
	//根据id查询用户
	public User findUserById(int id) throws IOException;
	//添加用户信息
	
	//删除用户信息
}
//Dao接口实现类
public class UserDaoImpl implements UserDao{
	//注入SqlSessionFactory对象,通过构造函数方法注入:
	private SqlSessionFactory sqlSessionFactory;
	public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}
	
	@Override
	public User findUserById(int id) throws IOException {
		
		SqlSession sqlSession=sqlSessionFactory.openSession();
		User user=sqlSession.selectOne("test.findUserById", id);
		
		sqlSession.close();
		return user;
	}

}
public class MybatisDaoTest {
	private SqlSessionFactory sqlSessionFactory;
	@Before//表示在其他方法之前执行
	public void set() throws Exception
	{
		String resource="SqlMapConfig.xml";
		//得到配置文件流
		InputStream inputStream=Resources.getResourceAsStream(resource);
		//创建会话工厂
		sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
	}
	
	@Test
	public void findUserById() throws Exception
	{
		UserDao userdao=new UserDaoImpl(sqlSessionFactory);//注入sqlSessionFactory
		User user=userdao.findUserById(10);
		System.out.println(user.getId()+user.getUsername());
	}
}

(3)总结原始dao开发问题:

①dao接口实现类方法中存在大量模板方法,加入能将这些代码提取出来,将会大大减轻程序员的工作量。

②调用sqlsession方法时将statement的id硬编码了。

③调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。


5、Mapper代理开发方法:

(1)程序员需要编写mapper.xml文件

(2)程序员编写mapper接口(相当于dao接口),需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。

(3)引入配置文件

开发规范:

①在mapper.xml中,namespace等于mapper接口地址

②mapper.java接口中方法名和mapper.xml中的statement的id一致

③mapper.java接口中方法的输入参数类型和mapper.xml中statement的parameterType指定的类型一致

④mapper.java接口中方法的返回值类型和mapper.xml中statement中resultType指定类型一致。

mybatis框架--学习笔记(上)_第2张图片
public interface UserMapper {
	/*
	(1)mapper.java接口中方法名和mapper.xml中的statement的id一致
	(2)mapper.java接口中方法的输入参数类型和mapper.xml中statement的parameterType指定的类型一致
	(3)mapper.java接口中方法的返回值类型和mapper.xml中statement的resultment中resultType指定类型一致。
	 */
	
	//根据id查询用户
	public User findUserById(int id) throws IOException;
	//根据用户名进行模糊查询
	public List findUserByName(String username) throws IOException;
	//插入数据
	public void insertUser(User user) throws IOException;
	//根据用户Id删除用户
	public void deleteUser(int id) throws IOException;
	//根据用户id修改用户
	public void updateUser(User user) throws IOException;
}
public class UserMapperTest {
	
	private SqlSessionFactory sqlSessionFactory;
	@Before
	public void set() throws Exception
	{
		String resource="SqlMapConfig.xml";
		//得到配置文件流
		InputStream inputStream=Resources.getResourceAsStream(resource);
		//创建会话工厂
		sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
	}
	@Test
	public void test1() throws IOException
	{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		
		User user=userMapper.findUserById(10);
		System.out.println(user.getUsername()+" "+user.getSex());
	}
}

在SqlMapConfig.xml配置文件中加载映射文件:


	
	
 	 


6、相关配置说明:

6.1、setting全局参数配置:

比如开启二级缓存,开启延迟加载

6.2、typeAliases(别名)--重点

在mapper.xml中,需要定义很多statement,在statement中,需要通过parameterType指定输入类型、需要通过resultType指定输出结果的映射类型。

如果在指定输入输出类型的全路径,不方便开发。可以通过在mapper.xml文件通过定义别名,方便开发

(1)单个定义

(2)批量定义



	
	 
	
	

6.3、typeHandlers(类型处理器):

mybatis中通过typeHandles完成jdbc类型和java类型的转化。通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义。

6.4、mappers(映射配置)

(1)通过resource加载单个映射文件

(2)使用class通过mapper接口加载映射文件

(3)使用package通过包名批量加载



	
	
        
		
	
	
		
	
	
	

6.5、输入映射:

通过parameterType指定输入参数的类型,类型可以是简单参数,hashmap,pojo的包装类型。

传递pojo的包装对象:

需求:完成用户信息的综合查询,需要传入的查询条件很复杂(可能包括用户信息、其他信息,比如商品、订单的),针对上边的需求,建议使用自定义的包装类。

步骤:

(1)pojo包装类

//与数据库表相对应的User类:
public class User {
	private int id;
	private String username;
	private String sex;
	private Date birthday;
	private String address;

        //省略get和set方法
}
//User拓展类
public class UserCustomer extends User {
	//可以在这个类中拓展用户信信息
}
//自定义的pojo包住类
public class UserQueryVo {
	//在这里包装所需要查询的条件
	
	private UserCustomer userCustomer;
	public UserCustomer getUserCustomer() {
		return userCustomer;
	}
	public void setUserCustomer(UserCustomer userCustomer) {
		this.userCustomer = userCustomer;
	}	
	
	//也可以包装其他的查询条件,订单、商品
}

(2)mapper.xml


(3)mapper.java

public interface UserMapper {
	//用户综合查询
	public List findUserList(UserQueryVo userQueryVo) throws IOException;
}

测试代码:

        //用户综合查询
	@Test
	public void findUserListtest() throws IOException
	{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		
		UserQueryVo userQueryVo=new UserQueryVo();
		UserCustomer userCustomer=new UserCustomer();
		userCustomer.setSex("男");
		userCustomer.setUsername("小鹏");
		
		userQueryVo.setUserCustomer(userCustomer);
		
		List list=userMapper.findUserList(userQueryVo);

		System.out.println(list);
	}

6.6、输出映射(resultType):

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。

如果查询出来的列名和pojo的属性有一个一致,就会创建pojo对象。

(1)输出简单类型:

用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。

查询出来的结果集只有一行且一列,就可以使用简单类型进行输出映射。

(2)输出pojo对象和pojo列表:

不管是输出的pojo单个对象还是一个列表,在mapper.xml中resultType指定的类型是一样的,在mapper.java指定的方法返回类型不一样。

    ①输出单个pojo对象,方法返回值是单个对象类型。

    ②输出pojo对象的list,方法返回值是List

生成的动态代理对象的过程中,是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是调用selectList(返回集合对象调用)

6.7输出映射(resultMap):

	
	
		
		
		
		
	
		

小结:使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。


7、动态sql:

(1)if判断:

mybatis框架--学习笔记(上)_第3张图片

(2)sql片段:

--定义sql片段:



	
	
		
			AND user.sex=#{userCustomer.sex}
		
		
			AND user.username LIKE '%${userCustomer.username}%'
					
	

--引入sql片段:



(3)foreach遍历:

		
	
	
		id=#{user_id}
	
 

	
	
		#{user_id}
	
//自定义的pojo包住类
public class UserQueryVo {
	
	//在这里包装所需要查询的条件
	
	//用户查询条件
	private List ids;//添加条件集合
	private UserCustomer userCustomer;
	
	public List getIds() {
		return ids;
	}
	public void setIds(List ids) {
		this.ids = ids;
	}
	public UserCustomer getUserCustomer() {
		return userCustomer;
	}
	public void setUserCustomer(UserCustomer userCustomer) {
		this.userCustomer = userCustomer;
	}
	
	//也可以包装其他的查询条件,订单、商品
}
//用户综合查询
	@Test
	public void findUserListtest() throws IOException
	{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		
		//创建UserMapper对象,mybatis自动生成mapper代理对象
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		
		UserQueryVo userQueryVo=new UserQueryVo();
		UserCustomer userCustomer=new UserCustomer();
		userCustomer.setSex("男");
		userCustomer.setUsername("小鹏");
		List ids=new ArrayList();
		ids.add(1);
		ids.add(5);
		ids.add(7);
		
		userQueryVo.setIds(ids);
		userQueryVo.setUserCustomer(userCustomer);
		
		int count=userMapper.findUserCount(userQueryVo);
		List list=userMapper.findUserList(userQueryVo);
		
		System.out.println(count);
		System.out.println(list);
	}

下篇:mybatis框架--学习笔记(下):https://blog.csdn.net/a745233700/article/details/81035781

你可能感兴趣的:(SSM+SSH框架)