Mybatis笔记

来源:互联网 发布:笔记本温度检测软件 编辑:程序博客网 时间:2024/06/15 01:57
1.mybatis是一个Java持久层框架,mybatis是对jdbc的封装。dao是持久层接口
2.jdbc编程中的问题:企业开发中,根据项目大小,特点进行技术选型,jdbc也是技术选型的参考。
jdbc操作数据库效率比框架要高。
3.PreparedStatement是预编译的statement,通过statement发起数据库的操作。Preparedstatement,
可以防止sql注入,执行数据库效率高。通过PreparedStatement发送到数据库的sql语句,数据库会对
这些语句进行缓存。二次发送时,可以省略编译的步骤。
4.jdbc问题总结:
①数据库连接频繁的创建与关闭,极大浪费数据库资源。
   *解决该问题可以用数据库连接池(c3p0)
②sql语句是硬性编码,硬性编码不利于系统维护。如果需求变更,需要修改sql,就需要修改Java代码
   *将sql语句统一配置在文件中,修改sql不需要修改Java代码
③向PreparedStatement占位符设置参数存在硬编码(参数位置)问题
   *将sql中的占位符配置在配置文件中
④遍历结果集存在硬编码问题
   *自动进行sql查询结果向Java对象映射
5.mybatis架构:
①它有一个最基础的配置文件,SqlMapperConfig.xml.(全剧配置文件)。它的作用是加载mybatis的运行环境
它的作用是加载mybatis的运行环经所需要的东西,如数据源,事务
②mapper.xml(配置sql语句)
  *mybatis的重点不是环境,而是sql语句,会写sql语句
6.SqlSessionFactory(会话工厂)的作用是创建SqlSession,sqlSession的作用是操作数据库
SqlSession是面向用户的接口,它里面的方法就是CRUD方法    
7.内部并不是SqlSession干活,而是Executor,数据库操作的执行器。
Excutor也是一个接口,它有默认执行器和缓存执行器
8.MappedStatement(mybatis的封装对象),封装sql语句
9.mapped,mapping,映射。
10.log4j.properties 作用:① Log4j是Apache的一个开放源代码项目,通过使用Log4j,
我们可以控制日志信息输送的目的地是控制台、文件、GUI组件②通过定义每一条日志信息的级别,
我们能够更加细致地控制日志的生成过程
11.POJO:简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
12.映射:在JavaBean类与数据库字段里,如果有想匹配的名称。数据库就会把字段的值赋给JavaBean类的属性
13.mapper.xml,命名方式:表明+mapper.xml
14.selectOne(String statement,Object obj),用于查找单条记录。否则会报这样的错误
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned
by selectOne(), but found: 2
selectList(String statement,Object obj).
15.占位符:①#{},表示一个占位符,向该占位符传参数时,mybatis会自动拼接。比如传入字符串,mybatis最终拼接好
的sql就是参数两边加单引号。
②${},表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中,缺点:因为是拼接串,不能防止sql注入
16.mybatis的配置:
①编写SqlMapConfig.xml:
--------------------------------------------------------------------------------------------------------------------
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/newstart"/>
                <property name="username" value="root"/>
                <property name="password" value="fusong"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="config\account.xml"/>
    </mappers>
</configuration>
①当mybatis与spring结合使用时,<environments这个标签就废掉了。
②<mappers>标签是mybatis提供的,要加到<configuration>里,进行sql语句的管理。
--------------------------------------------------------------------------------------------------------------------
②编写account.xml,
<?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">
<mapper namespace="account">
    <select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
        select * from account WHERE  money=#{id}
    </select>

    <select id="selectName" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE #{id}

    </select>
    <select id="selectName2" parameterType="string" resultType="com.fusong.POJO.Account">
        select * from account WHERE name LIKE "%${value}%"
    </select>
</mapper>
①id="selectByMoney",这里的id看作具有一个唯一标识的statement。在后面程序里我们要找它。
②#{},表示一个占位符,当这里面传入简单类型的参数时,这里面的名称随意
③parameterType:输入参数的类型,通过#{}接收程序里输入的参数
④resultType:输出结果的类型,不管输出单条还是多条记录,都要映射pojo类型
⑤namespace,名称空间。为了对sql语句进行隔离。mapper开发dao方式,后面会写它的特殊作用
--------------------------------------------------------------------------------------------------------------------
示例: SqlSessionFactory sqlSessionFactory = null;

    @Before
    public void init() throws IOException {
        String resource = "config/SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
 @Test
    public void test3() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<Account> accounts=null;
        accounts = sqlSession.selectList("account.selectName2", "付");

        sqlSession.close();
        for (Account account:accounts)
        {
            System.out.println(account);
        }

    }
--------------------------------------------------------------------------------------------------------------------
17.插入数据。配置如下:
    <insert id="insertAccount" parameterType="com.fusong.POJO.Account">
        INSERT  into account VALUES (#{IdCard},#{money},#{name},#{sex})
    </insert>
    <insert id="insertAccount2" parameterType="com.fusong.POJO.Account">
        INSERT  into account  (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
    </insert>
①#{},当为简单属性传值时,里面的名字任意起。当为对象属性传值时。名字要与数据库字段的名字相同。否则会报如下异常:
There is no getter for property named 'IdCa' in 'class com.fusong.POJO.Account'
②paramterType:输入参数类型。应写成对象类型。com.fusong.POJO.Account
--------------------------------------------------------------------------------------------------------------------
程序如下;
 @Test
    public void test2() {
        SqlSession session = sqlSessionFactory.openSession();
        Account account = new Account();
        account.setIdCard("456829645");
        account.setMoney((double) 88888);
        account.setName("段誉");
        account.setSex("男");
        session.insert("account.insertAccount", account);
        session.commit();
        session.close();
    }
---------------------------------------------------------------------------------------------------------------------
总结:插入对象时,输入参数为对象。#{}命名要与数据库字段一致

更新操作:<update id="updateAccount" parameterType="com.fusong.POJO.Account">
        UPDATE  account SET name="乔峰" WHERE name=#{NAME }
    </update>
---------------------------------------------------------------------------------------------------------------------
    public  void test1(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        Account account=new Account();
        account.setName("付fu");
        sqlSession.update("account.updateAccount",account.getName());
        sqlSession.commit();
        sqlSession.close();
    }
---------------------------------------------------------------------------------------------------------------------
18.mysql的uuid机制生主键的好处:使用uuid生成主键的好处是不用考虑数据库移植后主键冲突问题
19.企业开发进行技术选型,考虑mybatis和hibernate适用场景:
mybatis与hibernate的重要区别:
①mybatis,入门简单。对sql优化和修改十分方便。适合开发需求变更频繁的系统
②hibernate入门门槛高,他是一个ORM(对象关系映射)框架,适合需求稳定的,对象数据类型稳定的项目
20.SqlMapConfig.xml,是mybatis唯一的配置文件,是全局配置文件。mapper.xml是以statement(把一个sql语句称为一个statement)。
21.mybatis开发dao方式:
①原始dao方式
需要写dao接口和实现类
②mapper(代理的方式)
程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象
 *传统Dao的开发存在代码重复问题,如sqlSession.open(),sqlSession.close().
整个mybatis操作的代码模板重复
 *dao的实现类中存在硬编码。“account.InsertAccount”
mapper代理的方式可以避免以上的问题:
 要想让mybatis自动创建dao接口实现类的对象,必须遵循一些规则:
   ①mapper.xml中的namespace名称要与mapper接口中的类名称一致,目的是让
   mapper.xml与mapper.java关联。我们只需要创建接口,而不需要创建实现类
   ②'id' as sql statement in mapper.xml equals method in class
   <select id="selectNameBurriedly" parameterType="string" resultType="com.fusong.POJO.Account">
        select * from account WHERE name LIKE "%${value}%"
    </select>
   ③mapper.xml中的id,parameterType,resultType与接口中的一致
   ④注意创建代理对象的方法:
   AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
注意:在用${}时,里面的参数也是有讲究的,传value没事,但是传别的值就会报错:
There is no getter for property named 'id' in 'class java.lang.String'
---------------------------------------------------------------------------------------------------------------------
AccountMapper.xml配置:
<?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">
<mapper namespace="com.fusong.POJO.AccountDao">
    <select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
        select * from account WHERE  money=#{id}
    </select>
---------------------------------------------------------------------------------------------------------------------
只需要写一个接口:
public interface AccountDao {
    public  Account selectByMoney(Double money) throws Exception;
    public List<Account> selectNameBurriedly(String name) throws Exception;
}
---------------------------------------------------------------------------------------------------------------------
public class AccountDaoTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public  void init() throws IOException {
        String source= "config/SqlMapConfig.xml";
        InputStream inputStream= Resources.getResourceAsStream(source);
        sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public  void test1(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
       AccountDao accountDao= sqlSession.getMapper(AccountDao.class);
        try {
            Account account= accountDao.selectByMoney((double) 9999);
            sqlSession.close();
            System.out.println(account);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
---------------------------------------------------------------------------------------------------------------------
22.①SqlSession作用范围:
它是一个面向用户的接口,调用该接口的方法可操作数据库。由于sqlSession是线程不安全的
所以它的最佳应用范围在方法体内,被定义成局部变量    
②SqlSessionFactory
正常开发时,以单例方式管理sqlSessionFactory,整个系统运行中sqlSessionFactory只有一个实例
,将来和spring整合后由spring以单例方式管理sqlSessionFactory
③sqlSessionFactoryBuilder
把它看作工具类,用来生成sqlSessionFactory实例
23.使用mapper代理方式开发,mapper接口方法输入参数只有一个,但是可扩展性没有问题,
因为dao层是通用的,可以通过扩展POJO将不同的参数传入进去
24.建议使用properties,但不要在<properties>里定义属性,只引用定义的properties文件中属性。
里面的key的定义有一些规则,最好按jdbc.name的方式定义
25.在接口方法里加throws Exception
楼主,我觉得必须要抛出的、而且实现接口的类也应该抛出自己的异常    
26.ibatis我没用过,不过我对他有一些了解。我用过mybatis觉得他俩之间有些差别,但差别不是很大
。给我些许时间,我能胜任你们的工作
27.在SqlMapConfig.xml,settings全局参数配置,小心配置。mybatis没有这些性能参数,它会自动配置
28.定义别名:
<typeAlias type="com.fusong.POJO.Account" alias="Account"/>
使用别名:
<insert id="insertAccount2" parameterType="Account">
        INSERT  into account  (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
    </insert>

这里,type是别名映射的类型,alias是别名。
问题:如果用这种方法,我们需要为每一个类都取一个别名,繁琐。
这时我们需要考虑批量别名,定义:指定包路径,自动扫描包下面的POJO接口,并且自定自动定义别名
别名的默认为类名,首字母大小写都可以
 <typeAliases><!--取别名-->
        <package name="com.fusong.POJO"/>
    </typeAliases>
29.typeHandlers,类型处理器将Java类型和jdbc类型进行映射
mybatis提供很多类型处理器,一般情况下够用了
30.mappers,在SqlMapConfig里的mappers。
之前通过resource引用mapper的映射文件,mapper.xml。<mapper resource="config\AccountMapper.xml"/>
之后我们通过class引用mapper的接口,该接口的全限定名。<mapper class="com.fusong.POJO.AccountDao"/>
需要xml文件和Java类名称一致,而且在同一目录下
而今改善方法,批量配置mapper.xml文件,和上面一样,写一个<package>标签,通过package自动扫描mapper的接口。
 <mappers>
        <!--<mapper resource="conAccountDao.xml.xml"/>-->
        <!--<mapper class="com.fusong.POJO.AccountDao"/>-->
        <mapper resource="config\account.xml"/>    
        <package name="com.fusong.POJO"/>
    </mappers>
31.动态sql(重点):
where 1=1的解释:
①数据库在进行查询的时候,经常看到有的人使用where 1=1,主要是一些程序员的为了拼凑动态的sql语句,
如果使用不好会起到副作用的。是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
②where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
    <sql id="MydefinedSql">
        <if test="accountBoom!=null">
            <if test="accountBoom.name!=null and accountBoom.name!=''">
                AND name LIKE "%${accountBoom.name}%"
            </if>
            <if test="accountBoom.sex!=null and accountBoom.sex!=''">
                AND sex = "${accountBoom.sex}"
            </if>
        </if>
    </sql>
---------------------------------------------------------------------------------------------------------------------
<select id="selectNameBurriedly" parameterType="accountCustomer" resultType="Account">
        select * from account
        <where>
       <include refid="MydefinedSql"/>
        </where>
    </select>
    ---------------------------------------------------------------------------------------------------------------------
  @Test
    public  void test2() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
       AccountCustomer accountCustomer=new AccountCustomer();
       AccountBoom accountBoom=new AccountBoom();
       accountBoom.setName("付");
       //accountBoom.setSex("男");
       accountCustomer.setAccountBoom(accountBoom);
        List<Account> accounts=accountDao.selectNameBurriedly(accountCustomer);
        sqlSession.close();
        for (Account account1:accounts)
        {
            System.out.println(account1);
        }
    }
---------------------------------------------------------------------------------------------------------------------
32.ResultMap的配置:通过resultMap指定的POJO类型可与数据库字段映射,property是类型的属性值,column是数据库的字段名。
配置如下:
<resultMap id="MyResultMap" type="com.fusong.POJO.Account2">
        <id property="UserId" column="IdCard"/>
        <result property="Usermoney" column="money"/>
        <result property="Username" column="name"/>
        <result property="Usersex" column="sex"/>
    </resultMap>



    <select id="selectName" parameterType="string" resultMap="MyResultMap">
        SELECT  * FROM account WHERE NAME =#{VALUE }
    </select>

33.商品订单数据模型
①重要字段:不能为空的字段为重要字段
②子表指向父表
③数据库级别的关系就是外键
34.webservice是远程调用的东西,?
35.缓存的意义:
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,
从缓存中,从而提高查询效率,解决了高并发系统的性能问题。
36.mybatis的一级缓存和二级缓存:(我们是不使用mybatis缓存的)
①mybatis一级缓存是一个sqlSession级别,sqlSession只能访问自己的一级缓存的数据。
第一次发出一个查询sql,sql查询结果写入sqlSession的一级缓存中。同一个sqlSession再次发出相同的sql,就从
一级缓存中读取。如果两次中间出现commit操作,sql查询语句的一级缓存将会清空,下次只能重新到数据库读取。然后
存入缓存。
     一级缓存的配置:
   mybatis默认支持一级缓存不需要配置。
   注意:mybatis和spring整合后不支持一级缓存,整合后,spring按照mapper的模板去生成mapper代理对象。模板在最后
统一关闭sqlsession
②二级缓存是跨sqlSession,是mapper级别的缓存,对于mapper级别的缓存不同的sqlSession是可以共享的
   二级缓存的范围是mapper级别(mapper同一个命名空间),mapper命名空间里的。mapper以命名空间为单位创建map数据结构
map<key,value>
   二级缓存的配置:mybatis是没有默认的二级缓存的需要配置。
   在SqlMapConfig.xml里配置:
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
  在mapper.xml里配置,表示使用缓存:
  <cache/>
程序如下:
    public void test2() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        List<Account> account = accountDao.selectNameBurriedly("付");
        sqlSession.close();
        System.out.println(account);
        AccountDao accountDao2 = sqlSession2.getMapper(AccountDao.class);
        List<Account> account2 = accountDao2.selectNameBurriedly("付");
        sqlSession.close();
        System.out.println(account2);
    }
问题:这只是一个测试程序,当程序结束后释放内存所有的数据都清空了。该怎样从别的程序的
sqlSession里得到查询信息呢?
③每次查询,程序先看是否开启二级缓存,如果开启,从二级缓存的数据结构中取缓存数据
如果从二级缓存中没有取到,再从一级缓存中找。如果一级缓存也没有,则从数据库查询
④对于信息变化频率高的数据,需要禁用二级缓存,禁用方法:
在statement中设置useCache=false,可以禁用当前select语句的二级缓存,useCache默认情况下是TRUE
<select id="findOrderListResultMap" resultMap="OrderListMap" useCache="false">
⑤刷新缓存,flushcache,默认情况是true。
如果执行commit操作,对二级缓存进行刷新。
37.mybatis和ehcache缓存框架整合
mybatis二级缓存通过ehcache维护缓存数据。通过mybatis和ehcache框架进行整合,就可以把缓存数据的
管理托管给ehcache。
   *实现思路:在mybatis中提供一个cache接口,只要实现cache接口就可以把缓存数据灵活的管理起来

38.缓存框架:redis,memacahed,ehcache
39.mybatis和spring整合:
①让spring管理SqlSessionFactory
②让spring管理对象和dao
   *使用mybatis和spring整合,开发mapper代理以及原始dao接口
   会自动开启事务,自动关闭sqlsession
③让spring管理数据源(数据库连接池)

40.整合后配置文件:
①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:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:annotation-config></context:annotation-config><!--XML与注解混搭的时候用的,纯注解可以不写-->
    <!--加载配置文件-->
    <context:property-placeholder location="config/jdbc.properties"></context:property-placeholder>
    <!--配置数据库连接池-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.className}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--定义sqlSessionFactory属性-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--mybatis配置文件-->
        <property name="configLocation" value="config/SqlConfigMap.xml"/>
    </bean>
    <bean id="accountDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.fusong.POJO.AccountDao"/>
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
    <!--<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">-->
    <!--<property name="basePackage" value="com.fusong.POJO"/>-->
    <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->
    <!--</bean>-->
</beans>
注意:使用MapperFactoryBean需要一个个配置mapper类。
使用MapperScannerConfigurer会自动配置包下的mapper类。
②SqlConfigMap.xml的配置如下:
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--批量取别名-->
<typeAliases>
    <package name="com.fusong.POJO"/>
</typeAliases>
<!--批量配置mapper-->
<mappers>
    <package name="com.fusong.POJO"/>
</mappers>
</configuration>
③mapper.xml的配置如下:
<?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">
<mapper namespace="com.fusong.POJO.AccountDao">
    <resultMap id="ItemsResultMap" type="com.fusong.POJO.Items">
        <id property="Userid" column="id"/>
        <result property="UserName" column="name"/>
        <result property="Myprice" column="price"/>
        <result property="Mydetail" column="detail"/>
        <result property="Mypic" column="pic"/>
        <result property="Newdate" column="createtime"/>
    </resultMap>
    <select id="selectViaItems" parameterType="Items" resultMap="ItemsResultMap">
      SELECT  * FROM items WHERE name=#{UserName}
    </select>
</mapper>
41.mybatis逆向工程:
什么是逆向工程:我们平时在使用Mabatis框架进行Web应用开发的过程中,需要根据数据库表编写对应的Pojo类和Mapper映射文件,而这个过程重复单一且浪费时间。基于此,MyBatis官方为了让开发者更加方便快捷地使用MYBatis框架而不必编写繁琐的Pojo类以及Mapper文件,提供了一个十分简洁的逆向工程的工具。

Mybatis官方提供了逆向工程,可以针对数据库的表自动生成对应的mybatis代码(mapper.java\mapper.xml\pojo类)有了这个工具可以大大简化我们持久层代码的编写,和写代码过程中出错的概率。













 







原创粉丝点击