mybatis基础1

1、mybatis的框架

 解释:

1、  mybatis配置SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

  mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载

2、  通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂(其是一个接口)

3、  由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、  mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、  Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中

  一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、  Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement

  在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、  Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement

  在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

2、mybatis所需的jar和依赖的jar包

2.1下载mybatis

  mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases

  目录结构:

mybatis-3.2.7.jar----mybatis的核心包

lib----mybatis的依赖包

mybatis-3.2.7.pdf----mybatis使用手册

3、搭建mybatis工程

3.1加入mybatis核心包、依赖包、数据驱动包。

3.2配置log4j.properties,与classpath下

因为mybatis默认使用log4j作为输出日志信息。

# 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

 

3.3创建SqlMapConfig.xml

在classpath下创建SqlMapConfig.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>
    <!--和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
        <!--使用jdbc事务管理-->
            <transactionManager type="JDBC" />
        <!--数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybaits?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="admin" />
            </dataSource>
        </environment>
    </environments>
</configuration>

 

注意:SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理和连接池。

4、小实例

4.1po类

Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java如下:

数据库的表:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;

 

对应的user的po类

public class User {
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }
}

 

4.2创建sql映射文件

在classpath下的sqlmap目录下创建sql映射文件Users.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="test">
</mapper>

 

namespace:类似于c++中的namespace和Java中的package,用于隔离sql语句

4.3加载映射文件

mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:

<mappers>
        <mapper resource="sqlmap/User.xml"/>
</mappers>

 

4.3实现提供ID查询用户

4.3.1修改映射文件

在user.xml中添加:

<!-- 根据id获取用户信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        select * from user where id = #{id}
    </select>

 

 

注意:

1、id:sql语句唯一表示
2、parameterType:指定传入参数类型,对应pojo属性的类型
3、resultType:返回结果类型
4、#{}占位符,起到站位的作用,如果传入的是基本类型(string、long、int、boolean、float等),
    那么#{}中的变量名称可以是随意写,一般写属性

4.3.2测试程序

public class UserTest {
    
    @Test
    public void testFindUserById() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂创建会话
        SqlSession session = factory.openSession();
        //第一个参数:所调用的sql语句:namespece.+sql的id
        User user= session.selectOne("test.findUserById", 1);
        System.out.println(user);
        session.close();
    }
}

 

4.4根据用户名查询用户信息

4.4.1修改映射文件

在user.xml中添加:

    <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.wang.pojo.User">
        SELECT * from user where  username like '%${value}%'
    </select>

 

注意:

1、如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所映射的文件一个配置成集合范型的类型
2、${}拼接符,字符串原样拼接,如果传入的是基本类型(string、long、int、boolean、float等),
  那么%{}中的变量名称必须是value
  但有sql注入的风险

4.4.2测试程序

    @Test
    public void testFindUserByUserName()throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = factory.openSession();
        
        List<User> selectList= sqlSession.selectList("test.findUserByUserName", "王");
        System.out.println(selectList);
    }

 

4.5总结

4.5.1#{}和${}

a、#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,

  #{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

#{}:如果传入的pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....

b、${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,

  如果parameterType传输单个简单类型值,${}括号中只能是value。

  ${}:如果传入的pojo类型,那么${}中的变量名称必须是pojo中对应的属性.属性.属性.....

4.5.2parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。

resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

4.5.2selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常。

selectList可以查询一条或多条记录。

 

5、增删改查的实现

5.1增加(并且返回自增的主键id值)

5.1.1  映射文件:

在user.xml中添加:

    <insert id="insertUser" parameterType="com.wang.pojo.User">
    <!--
         执行SELECT LAST_INSERT_ID()数据库函数,返回自增主键
         keyProperty:将返回的主键放入传入参数的Id中保存
         order:当前函数相对于insert语句的执行顺序,在insert前是BEFORE之后是AFTER
         resultType:ID的类型,就是keyProperty中的类型
     -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>

 

注意:添加selectKey实现将主键返回

keyProperty:返回的主键存储在pojo中的哪个属性

order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after

resultType:返回的主键是什么类型

LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

5.1.2测试程序:

    //自动开启事务,但是要自己手动提交事务
    @Test
    public void testInsertUser()throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = factory.openSession();
        User user = new User();
        user.setSex("1");
        user.setAddress("北京");
        Date date = new Date();
        user.setBirthday(date);
        user.setUsername("大江");
        System.err.println(user.getId());

        session.insert("test.insertUser", user);
        //提交事务(没有不插入数据库)
        session.commit();
        System.err.println(user.getId());
        session.close();
    }

 

注意:mybatis是自动开启事务,但是要手动提交事务

衍生:UUID的主键获取

<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE" 
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) 
         values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

 

使用的是 order="BEFORE" 和select uuid()

5.2 删除用户

5.2.1  映射文件:

在user.xml中添加:

    <delete id="deleteUserById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete

 

5.2.2测试

    @Test
    public void testDeleteUserById()throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = factory.openSession();
        session.delete("test.deleteUserById", 29);
        session.commit();
        session.close();
    }

 

5.3修改

5.3.1修改user.xml

    <update id="updateById" parameterType="com.wang.pojo.User">
        update user set username=#{username} where id=#{id}
    </update>

 

5.3.2添加测试

    @Test
    public void testUpdateUserById()throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = factory.openSession();
        User user = new User();
        user.setId(28);
        user.setUsername("lllll");
        session.update("test.updateById", user);
        session.commit();
        session.close();
    }

 

SqlSession在讨论

6.1SqlSession的使用范围

SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。

通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

6.2SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,

因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

6.3SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,

一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

6.4SqlSession

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。

         每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

         打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:

         SqlSession session = sqlSessionFactory.openSession();

         try {

                  // do work

         } finally {

                session.close();

         }

 

7 DAO层的开发:

7.1原生(自定义实现)DAO层的开发

7.1.1 sql映射文件

<?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="test">
    <!-- 
    id:sql语句唯一表示
    parameterType:指定传入参数类型,对应pojo属性的类型
    resultType:返回结果类型
    #{}占位符,起到站位的作用,如果传入的是基本类型(string、long、int、boolean、float等),
    那么#{}中的变量名称可以是随意写,一般写属性
    -->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.wang.pojo.User">
        SELECT * from user WHERE id =#{id}
    </select>
    <!-- 
        如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所映射的文件一个配置成集合范型的类型
         ${}拼接符,字符串原样拼接,如果传入的是基本类型(string、long、int、boolean、float等),
    那么%{}中的变量名称必须是value
    注意:有sql注入的风险
     -->
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.wang.pojo.User">
        SELECT * from user where  username like '%${value}%'
    </select>
</mapper>

 

7.1.2 dao层

public interface UserDao {
    
    public User findUserById(Integer id);
    
    public List<User> findUserByName(String userName);

}

 

dao层的实现层

public class UserDaoImpl implements UserDao {

    private SqlSessionFactory factory;
    
    public UserDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    @Override
    public User findUserById(Integer id) {
        //sesion是线程不安全的,最佳在方法体内
        SqlSession session = factory.openSession();
        User user = session.selectOne("test.findUserById", id);
        return user;
    }

    @Override
    public List<User> findUserByName(String userName) {
         SqlSession sqlSession = factory.openSession();
         List<User> selectList= sqlSession.selectList("test.findUserByUserName",userName);
         return  selectList;
    }
}

 

7.1.3测试

public class UserDaoTest {
    
    private SqlSessionFactory factory;
    
    @Before
    public void setUp()throws Exception {
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void findUserById() throws Exception{
        UserDao userDao = new UserDaoImpl(factory);
        System.out.println(userDao.findUserById(1));    
    }
    
    @Test
    public void findUserByName() throws Exception{
        UserDao userDao = new UserDaoImpl(factory); 
        List<User> users =userDao.findUserByName("王");
        System.out.println(users);
    }

}

 

存在的问题:

原始Dao开发中存在以下问题:

1、Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法

2、 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。

 

7.2 Mapper动态代理方式   

7.2.1开发规范

Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper接口开发需要遵循以下规范:

  1、  Mapper.xml文件中的namespace与mapper接口的类全路径相同

  2、  Mapper接口方法名和Mapper.xml中定义的每个statement的id相同(sql语句的id)

  3、  Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

  4、  Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

注意:mapper类名与mapper映射文件名相同

7.2.2Mapper.xml(映射文件)

  定义mapper映射文件UserMapper.xml(内容同Users.xml),需要修改namespace的值为 UserMapper接口路径

将UserMapper.xml放在classpath 下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">
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
<!-- 根据id获取用户信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        select * from user where id = #{id}
    </select>
<!-- 自定义条件查询用户列表 -->
    <select id="findUserByUsername" parameterType="java.lang.String" 
            resultType="cn.itcast.mybatis.po.User">
       select * from user where username like '%${value}%' 
    </select>
<!-- 添加用户 -->
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select LAST_INSERT_ID() 
    </selectKey>
      insert into user(username,birthday,sex,address) 
      values(#{username},#{birthday},#{sex},#{address})
    </insert>

</mapper>

 

7.2.3Mapper.java(接口文件)

Public interface UserMapper {
    //根据用户id查询用户信息
    public User findUserById(int id) throws Exception;
    //查询用户列表
    public List<User> findUserByUsername(String username) throws Exception;
    //添加用户信息
    public void insertUser(User user)throws Exception; 
}

 

接口定义有如下特点:

  1、  Mapper接口方法名和Mapper.xml中定义的statement的id相同

  2、  Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同

  3、  Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同

7.2.4 加载UserMapper.xml文件

        <mapper class="com.wang.mapper.UserMapper"/>

 

注意:

使用类扫描的方式引入Mapper接口
1、接口名称和映射文件名称除扩展名外要完全相同
2、接口和映射文件要放在同一个目录下

或:

<package name="com.wang.mapper"/>

 

注意:

使用包扫描的方式批量引入Mapper接口
1、接口名称和映射文件名称除扩展名外要完全相同
2、接口和映射文件要放在同一个目录下

7.2.5测试

public class UserMapperTest {
    private SqlSessionFactory factory;
    
    @Before
    public void setUp()throws Exception {
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void findUserById() throws Exception{
        SqlSession session = factory.openSession();
        //通过getMapper实例化接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        
        User user= userMapper.findUserById(1);
        System.err.println(user);
    }
    
    @Test
    public void findUserByUserName() throws Exception{
        SqlSession session = factory.openSession();
        //通过getMapper实例化接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        
        List<User> users= userMapper.findUserByUserName("王");
        System.err.println(users);
    }
    
    @Test
    public void insertUser() throws Exception{
        SqlSession session = factory.openSession();
        //通过getMapper实例化接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setAddress("南京");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setUsername("孙");
        userMapper.insertUser(user);
        session.commit();
    }
}

 

7.3总结

  1、selectOne和selectList

  动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定

如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

  2、 namespace

  mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,

输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

 

8 SqlMapConfig.xml配置文件

8.1    配置内容

 SqlMapConfig.xml中配置的内容和顺序如下:

   properties(属性)

  settings(全局配置参数)

  typeAliases(类型别名)

  typeHandlers(类型处理器)

  objectFactory(对象工厂)

  plugins(插件)

  environments(环境集合属性对象)

    environment(环境子属性对象)

      transactionManager(事务管理)

      dataSource(数据源)

  mappers(映射器)

8.2 properties

SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

  在classpath下定义db.properties文件,

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybaits?characterEncoding=utf-8
jdbc.username=root
jdbc.password=admin

 

SqlMapConfig.xml引用如下:

    <environments default="development">
        <environment id="development">
        <!-- 使用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>

 

注意: MyBatis 将按照下面的顺序来加载属性:

  1、在 properties 元素体内定义的属性首先被读取。

  2、然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

 

8.3  typeAliases(类型别名)

8.3.1 mybatis支持别名:

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

map

Map

8.3.2自定义别名

在SqlMapConfig.xml中配置:

    <typeAliases>
    <!-- 
        定义单个pojo类别名
        type=类的全路径名称
        alias=别名
         -->
        <typeAlias type="com.wang.pojo.User" alias="User"/>
        
        <!-- 
            使用包扫描的方式批量定义别名
            别名就是类名,不区分大小写
         -->
        <package name="com.wang.pojo"/>
        
    </typeAliases>

 

因此:

    <select id="findUserByUserName" parameterType="string" resultType="User">
        SELECT * from user where  username like '%${value}%'
    </select>

 

8.4mappers(映射器)

Mapper配置的几种方法:

  8.1.  <mapper resource=" " />

  使用相对于类路径的资源

  如:<mapper resource="sqlmap/User.xml" />

  8.2  <mapper class=" " />

  使用mapper接口类路径

  如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>

  注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

  8.3  <package name=""/>

  注册指定包下的所有mapper接口

  如:<package name="cn.itcast.mybatis.mapper"/>

  注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

 

 

最终的SqlMapConfig.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>
    <properties resource="db.properties"/>
    <typeAliases>
    <!-- 
        定义单个pojo类别名
        type=类的全路径名称
        alias=别名
         -->
        <typeAlias type="com.wang.pojo.User" alias="User"/>
        
        <!-- 
            使用包扫描的方式批量定义别名
            别名就是类名,不区分大小写
         -->
        <package name="com.wang.pojo"/>
        
    </typeAliases>

    <!-- 和spring整合后 environments配置将废除 -->
    <environments default="development">
        <environment id="development">
        <!-- 使用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="user.xml"/>
        <!-- <mapper class="com.wang.mapper.UserMapper"/> -->
        
        <!-- 使用包扫描的方式批量引入Mapper接口
                1、接口名称和映射文件名称除扩展名外要完全相同
                2、接口和映射文件要放在同一个目录下 -->
        <package name="com.wang.mapper"/>
    </mappers>
</configuration>

 

UserMapper.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接口代理实现规则:
        1、映射文件中namespace要等于接口的全路径名
        2、映射文件中sql语句id要等于接口的方法名
        3、映射文件中传入参数类型要等于接口方法的传入参数类型
        4、映射文件中返回结果集类型要等于接口方法的返回值类型
 -->
<mapper namespace="com.wang.mapper.UserMapper"> 
<!-- 封装sql条件,封装后可以重用
    ID:是唯一表示 -->
    <sql id="userWhere">
        <!-- where 标签作用:
            1、会自动向sql中添加where关键字
            2、会自动去掉第一个条件的and关键字
             -->
        <where>
            <if test="username !=null and username !=''">
            and username like '%${username}%'
        </if>
        <if test="sex !=null and sex !=''">
            and sex =#{sex}
        </if>
        </where>        
    </sql>



        <!-- 
    id:sql语句唯一表示
    parameterType:指定传入参数类型,对应pojo属性的类型
    resultType:返回结果类型
    #{}占位符,起到站位的作用,如果传入的是基本类型(string、long、int、boolean、float等),
    那么#{}中的变量名称可以是随意写,一般写属性
    -->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.wang.pojo.User">
        SELECT * from user WHERE id =#{id}
    </select>
    <!-- 
        如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所映射的文件一个配置成集合范型的类型
         ${}拼接符,字符串原样拼接,如果传入的是基本类型(string、long、int、boolean、float等),
    那么%{}中的变量名称必须是value
    注意:有sql注入的风险
     -->
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.wang.pojo.User">
        SELECT * from user where  username like '%${value}%'
    </select>
    <!-- 
        #{}:如果传入的pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....
     如果要返回数据库自增主键,使用SELECT LAST_INSERT_ID()
     -->
    <insert id="insertUser" parameterType="com.wang.pojo.User">
    <!--
         执行SELECT LAST_INSERT_ID()数据库函数,返回自增主键
         keyProperty:将返回的主键放入传入参数的Id中保存
         order:当前函数相对于insert语句的执行顺序,在insert前是BEFORE之后是AFTER
         resultType:ID的类型,就是keyProperty中的类型
     -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
    
    <delete id="deleteUserById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
    
    <update id="updateById" parameterType="com.wang.pojo.User">
        update user set username=#{username} where id=#{id}
    </update>
    
    <!-- 只有返回一行一列的时候,那么返回值类型才可以是指定成基本类型 -->
    <select id="findUserCount" resultType="java.lang.Integer">
        select count(*) from user
    </select>
    
    <select id="findUserByUserNameAndSex" parameterType="com.wang.pojo.User" resultType="com.wang.pojo.User">
        select * from user
        <include refid="userWhere"></include>
    </select>
    
    <select id="findUserByIds" parameterType="com.wang.pojo.QueryVo" resultType="com.wang.pojo.User">    
        select * from user
        
        
        <where>
            <if test="ids !=null">
            <!-- foreach:循环传入集合的参数
                collection:传入的集合
                item:每次循环将循环出的数据放入这个变量中
                open:循环开始拼接的字符串
                close:循环结束拼接的字符串
                separator:循环中拼接分隔符
                 -->
                <foreach collection="ids" item="id" open="id in (" close=") " separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
    
    <!-- 一对一:自动映射 -->
    <!-- resultType返回的属性名与列命一直 -->
    <select id="findOrdersAndUser1" resultType="cn.itheima.pojo.CustomOrders">
        select a.*,b.id uid,username,birthday,sex,address 
        from orders a,user b 
        where a.user_id = b.id
    </select>
    
    <!-- 一对一:手动映射 -->
    <!--id:resultMap唯一标识
        type:将查询出的数据放入指定的对象中 
        注意:手动映射需要:指定数据库中表的字段名与java中pojo类的属性名称对应关系
    -->
    <!-- 以Orders为主,查询数据放入其中,把User放入其中当做属性 -->
    <resultMap type="com.wang.pojo.Orders" id="orderAndUserResultMap">
        <!-- id标签指定主键字段对应关系
            column:列,数据库中字段名称
            property:pojo中属性名
         -->
        <id column="id" property="id"/>
        <!--result指定非属性列的对应关系  -->
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        
        <!-- 指定单个对象的对应关系
            property:指定将数据放入Oders中的user属性中
            JavaType:支付user属性类型
         -->
        <association property="user" javaType="com.wang.pojo.User">
            <id column="uid" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>            
        </association>
    </resultMap>
    <select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
        select a.*,b.id uid,username,birthday,sex,address 
        from orders a,user b 
        where a.user_id = b.id
        </select>
        
        <resultMap type="com.wang.pojo.User" id="userAndOrderResultMap">
            <id column=" id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
            
            <!-- 指定对应的集合对象关系映射
                property:将数据放入User对象中的ordersList中
                ofType:指定ordersList的范型的类型
             -->
            <collection property="ordersList" ofType="com.wang.pojo.Orders">
                <id column="oid" property="id"/>
                <result column="user_id" property="userId"/>
                <result column="number" property="number"/>
                <result column="createtime" property="createtime"/>
                <result column="note" property="note"/>    
            </collection>
        </resultMap>
        <select id="findUserAndOrders" resultMap="userAndOrderResultMap">
            select a.*,b.id oid,user_id,number,createtime 
            from user a,orders b 
            where a.id=b.user_id
        </select>
</mapper>

 

 UserMapper.java

public interface UserMapper {
    
    public com.wang.pojo.User findUserById(java.lang.Integer id);
    
    //动态代理形式中如果返回结果集为list,那么mybatis会生成实现类的使用
    //会自动调用selectList方法
    public List<User> findUserByUserName(String name);
    
    public void insertUser(User user);
    
    public Integer findUserCount();
    
    public List<User> findUserByUserNameAndSex(User user);
    
    public List<User> findUserByIds(QueryVo vo);
    
    public List<CustomOrders> findOrdersAndUser1();
    
    public List<Orders> findOrdersAndUser2();
    
    public List<User> findUserAndOrders();


}

 

 

 

 

 

 

 

 

 

posted @ 2017-04-02 16:57  mslog  阅读(196)  评论(0编辑  收藏  举报