写点什么

年轻人的第一个 MyBatis 项目就要这样来学习,不走弯路

用户头像
小Q
关注
发布于: 2020 年 11 月 14 日

之前在我自己的公众号:Java架构师联盟发布了一篇mybatis-plus的文章之后,有小粉丝跟我说,现在刚开始学习Java,是不是可以不用学mybatis了直接学这个啊,听得我心里一阵后怕,总感觉自己带偏了他们的想法



其实我个人觉得,这不仅仅是他这种初学者,也是很多人的错误想法,就是觉得新的技术就是好的,不信?看这个,这也是一个初学者,在写代码的过程中遇到这样一个问题





原因,我直接上聊天记录吧





怎么样,这个问题简单吗?但是也凸显了一个问题,学习,尤其是开发这一行,真的不能激进,所以我借着今天的这个引子,整理今天的这份文章--mybatis,从最一开始的mybatis入门直到整合spring,并且附代码实现,刚开始学习的朋友可以实际操作一下,老牌程序员可以回顾一下当年的青葱岁月,哈哈哈哈哈



我们来看今天的正题吧



MyBatis前世



原生JDBC操作数据库的流程



加载驱动

获取链接 connection

获取statement

设置sql

给占位符 set值

执行sql,获取结果集

对结果集进行解析、封装

释放资源



原生的jdbc操作数据库的缺点:



频繁地进行获取链接、关闭链接,资源浪费。 数据库连接池

sql语句属于硬编码,维护不方便。并且需求变得可能性大,要经常地修改sql

占位符设置参数也属于硬编码,维护不方便

结果集解析过程也是硬编码,希望是能够自动地封装成我们自己开发的pojo对象中去



mybatis入门



mybatis 是一个持久层框架 ORM,他可以对jdbc的操作过程进行封装,使开发者只需关注sql本身,而无需去处理 注册驱动、获取链接、获取statement、结果集解析、资源释放等工作。



ORM :Object Ralational Mapping 对象关系映射简单地说,是通过描述对象和关系数据库之间的元数据的映射关系,将java中的对象持久化到关系数据库中。



mybatis配置



1、全局配置文件mybatis.xml(名字任意)配置mybatis的运行环境,包括连接池、事务等。

2、配置映射文件(配置sql)mapper.xml

3、SqlSessionFactory(会话工厂,通过配置文件获取的)创建SqlSession。

4、SqlSession(会话)操作数据库。

5、Executor(执行器)sqlSession是通过执行器来操作数据库的。

6、mapped Statement(底层封装对象)对数据库的操作进行封装,包括sql、输入参数、输出结果。



支持的输入输出参数类型



java基本类型

hashmap

自定义pojo对象




简单的Mybatis入门程序



项目架构





jar包





log4j.properties



# Global logging configuration



log4j.rootLogger=DEBUG, stdout



# Console output...



log4j.appender.stdout=org.apache.log4j.ConsoleAppender



log4j.appender.stdout.layout=org.apache.log4j.PatternLayout



log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

mybatis.xml



<?xml version="1.0" encoding="UTF-8" ?>



<!DOCTYPE configuration



      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"



      "http://mybatis.org/dtd/mybatis-3-config.dtd">



<configuration>



  <!--mybatis的运行环境



      mybatis与Spring整合后就不需要了



  -->



  <environments default="sqlServer">



      <environment id="sqlServer">



          <!-- 事务-->



          <transactionManager type="JDBC"></transactionManager>



          <!--数据库连接池-->



          <dataSource type="POOLED">



              <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"></property>



              <property name="url" value="jdbc:sqlserver://localhost:1433;database=ssm"></property>



              <property name="username" value="sa"></property>



              <property name="password" value="123456"></property>



          </dataSource>



      </environment>



  </environments>





  <mappers>



      <mapper resource="UsersMapper.xml"></mapper>



  </mappers>



</configuration>

Users.java



public class Users {



  private String username;



  private Date birthday;



  private String sex;



  private String address;





  public String getUsername() {



      return username;



  }





  public void setUsername(String username) {



      this.username = username;



  }





  public String getSex() {



      return sex;



  }





  public void setSex(String sex) {



      this.sex = sex;



  }





  public Date getBirthday() {



      return birthday;



  }





  public void setBirthday(Date birthday) {



      this.birthday = birthday;



  }





  public String getAddress() {



      return address;



  }





  public void setAddress(String address) {



      this.address = address;



  }



}

Users.mapper



<?xml version="1.0" encoding="UTF-8" ?>



<!DOCTYPE mapper



      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"



      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">



<!--



  namespace;命名空间



  作用:分割sql



  -->



<mapper namespace="UserMapper">



  <!--根据姓名查询用户信息-->



  <!--



      id用于标识映射文件中的sql,其实是statement的id



      parameterType:参数类型



      resultType:输出结果类型,单条结果的类型



      #{}:占位符。如果为简单类型,则可以通过#{value}来取值,也可以通过#{任意名字}来取值



  -->



  <select id="selectById" parameterType="int" resultType="com.me.pojo.Users">



      select * from users where id=#{id}



  </select>





  <!--${}字符串拼接,不能防止sql注入-->



  <select id="selectByUserName" parameterType="String" resultType="com.me.pojo.Users">



      /*传参为‘李%’*/



      select * from users where username like #{value}



      /*传参为‘李’*/



      /*select * from users where username like '${value}%'*/



  </select>



</mapper>

UsersTest.java



package com.me.test;





import com.me.pojo.Users;



import org.apache.ibatis.io.Resources;



import org.apache.ibatis.session.SqlSession;



import org.apache.ibatis.session.SqlSessionFactory;



import org.apache.ibatis.session.SqlSessionFactoryBuilder;



import org.junit.Before;



import org.junit.Test;





import java.io.IOException;



import java.io.InputStream;



import java.util.List;





public class UsersTest {



  private SqlSessionFactory sqlSessionFactory;



  @Before



  public void init() throws IOException {



      //获取全局配置文件



      InputStream in= Resources.getResourceAsStream("mybatis.xml");



      //获取SqlSessionFactory



      sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);



  }





  @Test



  public void test() throws IOException {







      //获取sqlSession



      SqlSession sqlSession=sqlSessionFactory.openSession();



      //执行sql



      Users user=sqlSession.selectOne("UsersMapper.selectById",1);



      System.err.println(user.getUsername());



      sqlSession.close();



  }





  @Test



  public void test2(){



      SqlSession sqlSession=sqlSessionFactory.openSession();



      List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李%");



      /*List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李");*/



      System.err.println(usersList);



      /*System.out.println(usersList.get(0).getUsername());



      System.out.println(usersList.get(1).getUsername());*/



  }



}




mybatis对数据库的常用操作



一、查询



  <select id="selectById" parameterType="int" resultType="com.me.pojo.Users">



      select * from users where id=#{id}



  </select>





  <!--${}字符串拼接,不能防止sql注入-->



  <select id="selectByUserName" parameterType="String" resultType="com.me.pojo.Users">



      /*传参为‘李%’*/



      select * from users where username like #{value}



      /*传参为‘李’*/



      /*select * from users where username like '${value}%'*/



  </select>

测试方法



  @Test



  public void selectByUserName(){



      SqlSession sqlSession=sqlSessionFactory.openSession();



      List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李%");



      /*List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李");*/



      System.err.println(usersList);



      /*System.out.println(usersList.get(0).getUsername());



      System.out.println(usersList.get(1).getUsername());*/



  }

二、新增



<!--添加用户信息-->



  <insert id="addUser" parameterType="com.me.pojo.Users">



      insert into users(id,username,password,address,birthday,sex) values(#{id},#{username},



      # {password},#{address},#{birthday},#{sex})



  </insert>





  <insert id="addUser2" parameterType="com.me.pojo.Users" keyProperty="id" useGeneratedKeys="true">



      insert into users(id,username,password,address,birthday,sex) values(#{id},#{username},#



      {password},#{address},#{birthday},#{sex})



  </insert>

测试方法



@Test
public void addUser(){
SqlSession sqlSession=sqlSessionFactory.openSession();
Users users=new Users(4,"王五","123",new Date(),"男","北京");
int res=sqlSession.insert("UsersMapper.addUser",users);
sqlSession.commit();
sqlSession.close();
}

@Test
public void addUser2(){
SqlSession sqlSession=sqlSessionFactory.openSession();
Users user=new Users(5,"王五","123",new Date(),"男","北京");
int res=sqlSession.insert("UsersMapper.addUser",user);
System.err.println("res:"+res);
System.err.println("users.getId:"+user.getId());
sqlSession.commit();
sqlSession.close();
}

三、修改



<update id="updateUser" parameterType="com.me.pojo.Users">
update users set password=#{password},address=#{address} where id=#{id}
</update>

测试方法



@Test
public void updateUser(){
SqlSession sqlSession=sqlSessionFactory.openSession();
Users user=new Users();
user.setPassword("newPass123456");
user.setAddress("济南");
user.setId(4);
int res=sqlSession.update("UsersMapper.updateUser",user);
sqlSession.commit();
sqlSession.close();
}

四、删除



<delete id="deleteUser" parameterType="int">
/*这里是简单类型,# { value } 中的value可以任意写*/
delete from users where id=#{id}
</delete>

测试方法



@Test
public void deleteUser(){
SqlSession sqlSession=sqlSessionFactory.openSession();
int res=sqlSession.delete("UsersMapper.deleteUser",5);
System.err.println("res:"+res);
sqlSession.commit();
sqlSession.close();
}




mybatis.xml的一些配置项



1、加载外部资源文件



<properties resource="db.properties"></properties>

2、起别名



<typeAliases>
<!--
起别名第一种方式
type:给哪个类起别名 alias:别名
-->
<!--<typeAlias type="com.me.pojo.Users" alias="user"></typeAlias>-->

<!--
起别名第二种方式:批量起别名
name:包,起的别名就是类名的全名,首字母大写、小写皆可
-->
<package name="com.me.pojo" />
</typeAliases>

3、SqlSessionFactory和SqlSession



//获取全局配置文件
InputStream in= Resources.getResourceAsStream("mybatis.xml");
//获取SqlSessionFactory
sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
//获取sqlSession
qlSession sqlSession=sqlSessionFactory.openSession();
//执行sql

SqlSessionFactory:它是通过全局配置文件获取的,SqlSessionFactoryBuilder创建的。一旦它被创建,就会在程序的执行期一直存在,因此只需要一个实例。也就是说希望它是单例的。SqlSession:作用是操作数据库,是线程不安全的。因而希望每个线程都有自己的sqlSession的实例。



4、工具类



package com.me.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;

static{
try {
//获取全局配置文件
InputStream in= Resources.getResourceAsStream("mybatis.xml");
//获取SqlSessionFactory
sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}

public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}

5、测试类



@Test
public void selectById() throws IOException {
//获取sqlSession
SqlSession sqlSession= MybatisUtils.getSqlSessionFactory().openSession();
//执行sql
Users user=sqlSession.selectOne("UsersMapper.selectById",1);
System.err.println(user.getUsername());
sqlSession.close();
}




Spring与Mybatis整合



mybatis:dao层,操作数据库,需要单例的SqlSessionFactory工厂。spring:容器,管理对象。可以将SqlSessionFactory、事务、连接池以及mapper的动态代理交给spring来做。



applicationContext.xml



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/spring-aop.xsd">

<!--加载外部资源文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--数据库连接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

<!--配置SqlSessionFactory,通过Spring来管理会话工厂-->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源:因为要使用SqlSession操作数据库-->
<property name="dataSource" ref="dataSource"></property>
<!--加载mybatis的全局配置文件-->
<!--<property name="configLocation" value="classpath:mybatis.xml"></property>-->
<!--Spring起别名-->
<property name="typeAliasesPackage" value="com.me.pojo"></property>
</bean>

<!--mapper动态代理 通过扫描批量加载mapper接口来创建代理bean,这些bean的名字是接口名字(首字母小写)-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定mapper接口的包路径-->
<property name="basePackage" value="com.me.mapper"/>
</bean>

<!--注解扫描-->
<context:component-scan base-package="com.me.service"></context:component-scan>
</beans>

UsersService.java



public interface UsersService {
public Users selectById(int id);
}

UsersServiceImpl



@Service("userService")
public class UsersServiceImpl implements UsersService {

@Autowired
private UsersMapper usersMapper;

@Override
public Users selectById(int id) {
return usersMapper.selectById(id);
}
}

测试类



public class AppTest {
@Test
public void selectById(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UsersService usersService= (UsersService) applicationContext.getBean("userService");
Users user=usersService.selectById(1);
System.err.println(user.getUsername());
}
}

总结



好了,不知道看完今天的内容大家感觉怎么样,有没有收获,我基本是按照从入门开始,逐步的往里面填充一些知识的顺序将mybatis进行了整理,那这个时候,我想,在实际的学习过程中你肯定还会遇到一些这样那样的问题,但是千万不要突进,脚踏实地,就从一些基础的,无聊的东西开始一点点的学习,网络上那些说这个牛,哪个好的,他肯定有一门傍身的技术作为基础,所以才能打到他说的那个层次



最后,所有程序员都能当架构师,哈哈哈哈哈



发布于: 2020 年 11 月 14 日阅读数: 17
用户头像

小Q

关注

还未添加个人签名 2020.06.30 加入

小Q 公众号:Java架构师联盟 作者多年从事一线互联网Java开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果能为您提供帮助,请给予支持(关注、点赞、分享)!

评论

发布
暂无评论
年轻人的第一个MyBatis项目就要这样来学习,不走弯路