MyBaties入门

1.什么是mybatis,有什么用?

  1. Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时 只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性 能,灵活度高。
  2. MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数 据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
  3. 通过 xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最 后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。(从执行 sql 到返 回 result 的过程)

orm(Object Relational Mapping)对象关系映射框架

实体类映射到一个数据库表,类中的属性映射到表的字段

(执行效率 高–>低) jdbc–>dbutils–>mybatis–>hibernate,jpa,mp

优点

  1. 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任 何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
  2. 与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不 需要手动开关连接;
  3. 很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
  4. 提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射 标签,支持对象关系组件维护。

2.快速入门

  1. 创建java工程
  2. 添加mybatis与mysql数据库驱动包。
  3. 在mysql数据库下创建数据库表。
  4. 在entity包下创建数据库表对应的实体类。
  5. 在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="userMapper">
   <-- parameterType表示查询参数类型;resultType表示数据库查询结果的每行记录封装类型。-->
    <select id="selectUserByKey" parameterType="int" resultType="User">
        select * from tb_user where uid = #{uid}
    </select>
</mapper>
  1. 在类路径下创建mybatis的xml核心配置文件,注意引入映射文件。
  2. 使用mybatis的核心api对象加载配置文件。
<?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>
    <!--加载外部的properties资源文件-->
    <properties resource="jdbc.properties">
    </properties>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启事物不自动提交手动提交事物-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--配置该包下的所有类都有简写的名-->
    <typeAliases>
        <package name="com.javasm.entity"/>
    </typeAliases>
    <!--数据库环境-->
    <environments default="dev">
        <environment id="dev">
            <!--事务管理器,使用JDBC的事务管理方法-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.Driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件-->
    <mappers>
        <mapper resource="com\javasm\dao\userMapper.xml"/>
        <mapper resource="com\javasm\dao\userMapper2.xml"/>
    </mappers>
</configuration>

8.测试引入junit4

public class SqlSessionFactoryUtil {
    
    
    private static SqlSessionFactory ssf=null;
    static{
    
    
        InputStream input = null;
        try {
    
    
            input = Resources.getResourceAsStream("mybatis-config.xml");
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        ssf = new SqlSessionFactoryBuilder().build(input);
    }
    public static SqlSessionFactory getSqlSessionFactory(){
    
    
        return ssf;
    }
}

② 创建junit测试类
public class TestStart {
    
    
    private static SqlSessionFactory ssf = null;
    private SqlSession session = null;
    @BeforeClass
    public static void initFactory() {
    
    
        ssf = SqlSessionFactoryUtil.getSqlSessionFactory();
    }
    @Before
    public void openSession() {
    
    
        session = ssf.openSession();
    }
    @Test
    public void testGetUserById() throws IOException {
    
    
        //SqlSession的selectOne方法的第一个参数是namespace.id组成的字符串,
        //第二个参数是查询参数,且当前只能传入一个参数。
        Object result = session.selectOne("userMapper.getUserById", 1);
        System.out.println(result);
    }
    @After
    public void closeSession() {
    
    
        session.close();
    }
    @AfterClass
    public static void closeFactory() {
    
    
        ssf = null;
    }
}

3.mybatis的核心对象(重要)

1.SqlSessionFactoryBuilder:构建者模式应用,有build方法,用来构建复杂的单例的SqlSessionFactory对象

生命周期:用完即销毁.其生周期只存在于方法体内,可重用。

2.SqlSessionFactory:工厂模式应用,与构建者的区别在于工厂生产N个对象.实现类:DefaultSqlSessionFactory,该对象中持有的DataSource

生命周期:全局唯一.放在web项目下理解,tomcat启动期间,只有一份Factory.单例

3.SqlSession:数据库会话对象,实现类DefaultSqlSession.该对象内部有curd方法执行数据库表操作.(selectOne,selectList,insert,delete,update,getMapper),只有getMapper方法重要代理模式使用.

生命周期:每次数据库操作临时打开会话,用完关闭会话.需要创建它每个线程都有自己的 SqlSession 实例,SqlSession实例是不能被共享,也不 是线程安全的。

4.dao接口的代理对象:


4.详细了解mybatis的核心文件配置

标签文件有先后顺序.dtd文件能看选后顺序

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
  1. properties标签,用来加载外部properties文件.
 <properties resource="jdbc.properties">
 </properties>
//引入
<dataSource type="POOLED">
    <property name="driver" value="${jdbc.Driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</dataSource>
  1. environments标签,用来配置数据库连接信息.
  2. mappers标签,用来加载外部的xml映射文件
  3. settings标签,用来修改mybatis运行的默认行为.
 <settings>
 		//展示自带的日志
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        //数据库用连字符起字段名的忽略.把数据库中的_分割的列名,映射到实体类的驼峰属性名
        <setting name="mapUnderscoreToCamelCase" value="true"></setting>
 </settings>
  1. typeAliases:用来对指定包下的类自动起别名.要求整个项目下不能有同名的类
<typeAliases>
		//具体类起别名,别名影响的是映射文件中的parameterType与resultType属性
        <!--<typeAlias type="com.javasm.sys.entity.Sysuser" alias="sysuser"></typeAlias>-->
        //该包下所有文件起别名,别名就是文件名
    	//不同的包不能起同名的类
        <package name="com.javasm"></package>
</typeAliases>

5.掌握mybatis的映射文件(重要)

1.映射文件中常用标签
  • select标签:用来执行select语句
<!--
      parameterType:参数类型,可以写别名
      resultType:把查询结果的一行记录封装的类型(map,实体对象,String,Double,Integer)
      如果parameterType是简单类型的话,#{随便写}
      如果parameterType是实体类,#{类的成员变量名}
      如果parameterType是map,#{map的key}/params1,params2
-->
	//简单类型下parameterType可以省略
    <select id="selectUserByKey" parameterType="int" resultType="sysuser">
      select * from sysuser where uid=#{uid}
    </select>
  • insert
<!--生成key模式  主键对应的属性名-->获得自增id
<!-- useGeneratedKeys="true" keyProperty="uid"-->
<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="uid" >
       insert into tb_user(uid, uname, uphone) values (#{uid},#{uname},#{uphone})
</insert>
@Test
public void addUser(){
    
    
    User user = new User();
    user.setUphone("5423423");
    user.setUname("sdsa");
    System.out.println(session.insert("userMapper.addUser", user));//返回受影响的行记录数  
    System.out.println(user.getUid());//返回刚刚新增的id
    session.commit();//配置文件开启了事物
}
  • update
<update id="updataUser" parameterType="user">
    update tb_user set uname=#{uname},uphone=#{uphone} where uid=#{uid}
</update>
@Test
public void updataUser() {
    
    
    User user = new User();
    user.setUid(9);
    user.setUname("赵鑫阳a");
    System.out.println(session.update("userMapper.updataUser", user));//受影响行记录数
    session.commit();
}
  • delete
<delete id="delUserById" parameterType="int">
    delete from tb_user where uid=#{uid}
</delete>
@Test
public void delUser() {
    
    
    System.out.println(session.delete("userMapper.delUserById", 9));
    session.commit();
}
2.#{}与${}使用

两者都是用来获取参数拼接sql.

#{}:mybatis内会使用PreparedStatement对象进行sql语句预编译,使用**?参数占位符**来传参,防止sql注入攻击.查询参数必须使用#{}

${}:不使用?占位符传参,而是字符串替换,就是把{}替换成变量的值,大多数用在对表格指定字段的排序使用,传入排序字段和排序规则(select * from user order by id)这个id是指定字段不能使数据/查询指定字段


6.getMapper

  1. 映射文件的namespace写为当前映射文件对应的接口类的全类名

    <mapper namespace="com.javasm.dao.UserDao">

  2. 创建对应实体类的接口写方法和映射文件的id值相同

  3. 测试类调用

//传入dao接口的类对象,返回的是指定类的代理对象,映射文件的namespace必须是dao接口的全名
@Test
public void selectUserByKey() {
    
    
    //传入一个接口对象返回一个接口的代理对象
    UserDao mapper = session.getMapper(UserDao.class);
    User user = mapper.selectUserByKey(4);//根据类名,方法名==namespace.id,底层仍然调用selectOne
    System.out.println(user);
}

xml映射文件中的namespace不再随意,必须是mapper接口的名称(含包名)。

调用SqlSession会话对象方法时,通过getMapper方法返回mapper接口类型的对象是当前接口的代理对象


6.多参数操作

  • 把多个参数封装到map

    User selectUserByIdAndPhone(User user);

  • 把多个参数封装到实体对象

    User selectUserByIdAndPhone2(Map<String,Object> map);

  • 在dao接口的方法中仍然保持多形参,形参前使用@Param注解,这种方式是mybatis底层把多个参数封装到map.map的key默认0,1,2…或者param1,param2…也可以通过@Param注解指定key

    User selectUserByIdAndPhone3(@Param("uid_key") Integer uid,@Param("uphone_key") String phone);


7.模糊查询

  1. 在映射文件中的sql语句中使用%
<select id="selectUsersByPhone" parameterType="String" resultType="sysuser">
    //idea环境下这个语句会报错但是不影响运行
        select * from sysuser where uphone like "%"#{uphone}"%"
</select>

2.传入的字符串参数中带有%

@Test
public void test4_selectUsersByPhone() {
    
    
    SysuserDao mapper = session.getMapper(SysuserDao.class);
    List<Sysuser> sysusers = mapper.selectUsersByPhone("%2%");
    System.out.println(sysusers);
}

8.查询结果返回map

对于复杂的多表级联查询,返回结果无法封装实体类,建议resultType=“map”,直接封装为map对象即可

1.两表联查询单个结果集

  Map<String,Object> seletUserAndPowerById(Integer uid);
 <select id="seletUserAndPowerById" parameterType="int" resultType="map">
        select * from tb_user u,tb_power p where p.uid=u.uid and u.uid=#{uid}
  </select>
@Test
public void seletUserAndPowerById() {
    
    
    UserDao mapper = session.getMapper(UserDao.class);
    Map<String, Object> map = mapper.seletUserAndPowerById(4);
    System.out.println(map);
    session.commit();
}

1.两表联查询多个结果集

List<Map<String,Object>> seletUserAndPowerById(Integer uid);
<select id="seletUserAndPowerById" parameterType="int" resultType="map">
    select * from tb_user u,tb_power p where p.uid=u.uid and u.uid=#{uid}
</select>
@Test
public void seletUserAndPowerById() {
    
    
    UserDao mapper = session.getMapper(UserDao.class);
    List<Map<String, Object>> list = mapper.seletUserAndPowerById(4);
    System.out.println(list);
    session.commit();
}

注意点:

  • 需要命名的地方,绝对不允许单个单词;

  • 类的成员变量不建议long,不允许基本类型(Long数据,前端js代码不支持,数据丢失精度)

  • 表字段名不允许u_name/uName(一个字母_单词)set,get方法名不规范,成员变量名不允许uName;成员变量名不允许is开头;

  • 表中类型datetime,date,timestamp,实体类的成员变量类型,建议使用String;

  • 23种gof设计模式


  1. 记忆框架的使用,

  2. mybatis常见错的位置:

常见错误
  • 映射文件忘记在配置文件引入.(配置文件中的mapping忘记写)
//Mapped Statements collection does not contain value for userMapper.selectUserByKey
  • 映射文件中的namespace与id在写的时候写错
//Mapped Statements collection does not contain value for userMapper.selectUserByKeys
  • 映射文件中的id重复了
//Mapped Statements collection already contains value for userMapper.selectUserByKey
  • properties文件的配置不加载,key很可能写的单个单词
//url--->jdbc.url

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false false (在 3.4.1 及之前的版本中默认为 true)
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false False
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 任意正整数 未设置 (null)
defaultResultSetType 指定语句默认的滚动策略。(新增于 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) 未设置 (null)
safeRowBoundsEnabled 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 true | false False
safeResultHandlerEnabled 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 true | false True
mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false False
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置
proxyFactory 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 以上)

猜你喜欢

转载自blog.csdn.net/weixin_45948874/article/details/114780106