首页 > 其他 > 详细

Mybatis

时间:2020-10-25 17:48:54      阅读:39      评论:0      收藏:0      [点我收藏+]

其实Javaweb就想直接加在里面但,感觉不全面就算了吧.....

首先为什么使用Mybatis?

在没有mybatis前,java连接数据库和写sql语句是怎么样的?!

public class IStudentDaoImpl implements IStudentDao {

    private Connection conn=null;
    private PreparedStatement pst=null;
    private ResultSet rs=null;

    /**
     * 通过ID执行单个查询
     * @param i
     * @return
     */
    @Override
    public List<Student> selectOne(long i) {
        List<Student> list = new ArrayList<>();
//        查询表中所有数据
        String sql="Select * FROM student where id=?";
        try {
            conn = JDBCUtil.getConnection();
//        预编译语句
            pst = conn.prepareStatement(sql);
            pst.setLong(1,i);
//        执行DDL操作
            rs = pst.executeQuery();

            list = JDBCUtil.loopSet(rs);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(pst,conn,rs);
        }
        return list;
    }
}

数据库连接

public class JDBCUtil {
    private static DataSource ds;
    private static Properties p=new Properties();

    static {
        try(    //java6的新特性,try()中自动关闭
                InputStream in = Thread.currentThread().getContextClassLoader()
                        .getResourceAsStream("db.properties")
                ) {

            p.load(in);


            /*Class.forName(p.getProperty("driverClassName"));*/
            ds= DruidDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static Connection getConnection() throws SQLException {
       /* try {
            return DriverManager.getConnection(p.getProperty("url"),
                    p.getProperty("username"),p.getProperty("password"));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;*/

        return ds.getConnection();
    }

 

我们需要在这里面写sql,连接数据库,关闭数据库连接,提交事务,

那么假设我们有很多的表要写,那这个工作量有多大?且sql和java代码混杂在一起,以后维护起来方便吗?!

 

他可以解决我们什么问题?

帮我们把sql语句抽取出来,让代码便于维护,分离

连接数据库,再也不用写在java代码里一个配置文件搞定连接烦恼

 

环境准备

mybatis-xxx.jar

mysql-connector-java-xxx-bin.jar

2.mybatis:mybatis-config.xml配置文档

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="dev_mysql">
    <environment id="dev_mysql">
        <!--Mybatis 内置事务管理器-->
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="admin"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
      <!--mapper文件的路径-->
    <mapper resource="xxx.xml"/>
  </mappers>
</configuration>

3.mapper映射文件:XxxMapper.xml

mybatis中访问的SQL语句都是在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 : 命名空间(通俗说法: 给当前映射文件的唯一标识:起一个唯一的名字)    
 -->
<mapper namespace="cn.ss.mybatis.pojo.UserMapper">
    <!-- 新增操作
        id: 当前功能的唯一标识,和接口方法同名
        parameterType : 参数的类型
        useGeneratedKeys:是否返回数据库生成的主键 true是/false否 
        keyProperty : 数据库主键对应java的pojo对象的属性
        keyColumn : 数据表的主键列明
     -->
    <insert id="insertUserInfo" parameterType="User" 
        useGeneratedKeys="true"
        keyProperty="id"
        keyColumn="id"
    ></mapper>

 

其实获取连接对象还是需要用到连接池对象(为什么使用连接池对象的原因是为了减少对数据库资源浪费)

举个栗子:

在没有使用数据库连接池之前,我们每次调用数据库都要开一个数据库连接

而数据库的连接是有限的,当一个项目为了一些操作不断的开启数据库连接

这样最终会导致数据库崩溃.

连接池就是起到,当你使用完数据库连接后,调用关闭并不是放回数据库,而是放入数据库连接池等待下次调用

 

 

而mybatis的数据库连接对象时SqlSessionFactory 中获取SqlSession

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class
);
  Blog blog = mapper.selectBlog(101);
}

注意:这里的(BlogMapper.class)指的是接口文件的字节码文件,要匹配到接口修改xml文件的空间命名!!!!!

另外注解和通过SqlSession实例来直接执行SQL的我就不写了(有想了解的百度吧)

 

ResultMap(正确书写可以帮助你得到提交时的错误)

 ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。

type 类的完全限定名, 或者一个类型别名 (内置的别名可以参考上面的表格).

association – 一个复杂类型的关联;许多结果将包装成这种类型

嵌套结果映射 – 关联可以指定为一个 resultMap 元素,或者引用一个

<resultMap id="baseResultMap" type="Department">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--关联属性是集合类型 使用collection来配置
             select 发送而外的sql
             column 而外sql参数之前sql那些列的值
             property 查询结果封装部门对象什么属性
        -->
        <collection select="cn.wolfcode.mapper.EmployeeMapper.queryById" column="id" property="employees"/>
    </resultMap>

 

命名参数@Param

经过JDBC的同学,应该已经尝试过想在方法中传递多个参数,的操作吧?!

然后取不到值,其实当你传递多个参数给mapper时,这些参数就会被封装到一个map中

而获取的方法式

<select id="insertUserInfo" resultType="User" >
select * from user where password=#{param1} and username=#{param2}
</select>

通过默认命名获取参数

而为了解决这种,不清晰的方式mybatis,提供了注解,让你在传递多个参数前提前给个命名

void selectOne(@Param("username")String username,@Param("password")String password)

 

动态SQL

优势:以前拼接的时候需要注意的空格、列表最后的逗号等,现在都可以不用手动处理了

  • if

    可选的查找薪水功能

<select id="QueryByList" restult="employee">
SELECT id,name,salary 
FROM employee
where 
    <if test="minSalary !=null">
        salary &gt;=#{minSalary}
    </if>
    <if test="maxSalary !=null">
     and    salary &lt;=#{minSalary}
    </if>
</select>

 

  • choose (when, otherwise)

   在不想使用所有的条件,而只是想从多个条件选择一个

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

 

  • trim ,where, set

   前面案例运用if解决了可选查找的问题,但是假设两个条件多不成立,或前一个不成立呢?

<select id="QueryByList" restult="employee">
SELECT id,name,salary 
FROM employee
    <where>
    <if test="minSalary !=null">
        salary &gt;=#{minSalary}
    </if>
    <if test="maxSalary !=null">
     and    salary &lt;=#{minSalary}
    </if>
    </where>
</select>

 

  •   foreach
<!--    colletion 遍历数组或集合的key,或者属性名
        open 遍历开始拼接的字符串
        index 遍历索引
        item 遍历元素
        separator 每遍历一个元素拼接的字符串
        close 遍历拼接结束的字符串

-->
    <delete id="batchDelete">
        delete from employee where id IN
        <foreach collection="ids" open="(" item="id" separator="," close=")">
            #{id}
        </foreach>

 

Mybatis的#和$的区别

相同点:

都可以获取对象(Map对象或者JAVABean对象)信息

不同点:

使用#传递的参数会先转换为,无论传递是什么类型数据都会带一个单引号;$传递的参数,直接把值作为SQL语句的一部分

使用#支持把简单类型参数作为值;$不支持简单类型为值

使用#好比使用PrepareStatement,没有sql注入的问题,比较安全;而$则反之

但这样是不是$就没用了呢?!

其实不然例如ORDER BY 或GROUP BY字句获取参数值使用$,因为这样会直接拼接在SQL上

(#加引号导致找不到列),因此若需要获取参数才使用#

**(使用$可以携带常量)

 

Mybatis

原文:https://www.cnblogs.com/weiwo/p/13866844.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!