Mybatis--02

1.基于代理Dao的CRUD操作


1.1根据ID进行查询

涉及到对数据库的操作,所使用的表还是之前已经创建好的User表。
  • 在持久层接口添加 getUserById 方法。
	public interface IUserDao {
    /**
     * 查找所有用户
     * @return
     */
    List<User> findAll();
     /**
     * 根据id查找用户
     * @param id
     * @return
     */
    User getUserById(Integer id);
  • 在用户的映射配置文件IUserDao.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.zut.dao.IUserDao">
	<!-- 查找所用 -->
    <select id="findAll" resultType="com.zut.domain.User">
       select * from user
    </select>
    <!-- 根据id查找用户 -->
	<select id="getUserById" parameterType="java.lang.Integer" resultType="com.zut.domain.User">
	        select * from user where id=#{aa}
	</select>
</mapper>
  • 这里的 parameterType 用于指定传入的参数类型。
  • sql语句中使用的 #{ }
    则代表一个占位符,相当于JDBC中的?,用于执行语句时替换实际的数据。具体的数据内容由#{}里面的内容决定。
  • 因为这里传入的参数为基本类型,所以此处可以随意写,任何内容均可。
  • 在测试类中添加测试
public class mybatistest {

    private IUserDao iUserDao;
    private SqlSession session;

    //初始化
    @Before
    public void init() throws Exception{
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产sqlSessino对象
        session = factory.openSession();
        //4.使用SqlSession创建Dao的代理对象
        iUserDao = session.getMapper(IUserDao.class);
    }

    @After
    public void destory(){
        session.commit();
        //释放资源
        session.close();
    }
     /**
     * 测试根据id获取用户
     */
    @Test
    public void getUserById(){
        User user = iUserDao.getUserById(45);
        System.out.println(user);
    }
}

测试类中 destory 方法中写了一句代码:session.commit(),它的作用是进行事务的手动提交。如果要设置自动提交。可以在 openSession方法中设置参数true。
当然此处我们可以不写这一句代码,因为这里测试的是查询方法。

1.2 保存操作

  • 同样,第一步还是在持久层接口中添加方法。
    /**
     * 保存操作
     */
    void saveUser(User user);
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<!-- 保存操作 -->
    <insert id="saveUser" parameterType="com.zut.domain.User"> 
        insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
    </insert>

这里的sql语句中也用到了#{ },但注意,此处括号里的内容不能乱写!!!
它必须和实体类中的属性名进行一一对应,这里实际上是通过实体类的getXxx()方法来拿到具体的值。

  • 在测试类中添加测试
public class mybatistest {

    private IUserDao iUserDao;
    private SqlSession session;

    //初始化
    @Before
    public void init() throws Exception{
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产sqlSessino对象
        session = factory.openSession();
        //4.使用SqlSession创建Dao的代理对象
        iUserDao = session.getMapper(IUserDao.class);
    }

    @After
    public void destory(){
        session.commit();
        //释放资源
        session.close();
    }
/**
     * 测试保存用户
     */
    @Test
    public void testsaveUser(){
        User u = new User();
        u.setUsername("王老五");
        u.setBirthday(new Date());
        u.setSex("女");
        u.setAddress("北京市莲花大道");
        System.out.println("保存前:" + u);
        iUserDao.saveUser(u);
        
        System.out.println("保存后:" + u);
    }
}

注意:这里的session.close一定不能省略,否则会造成保存不成功,因为保存的操作涉及到事务的操作,必须进行事务的提交。

  • 扩展操作:新增用户id的返回值

新增用户后,同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。

<insert id="saveUser" parameterType="com.zut.domain.User">    <!-- parameterType代表参数类型 -->
       <!-- 同时获取id的返回值 -->
       <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
           select LAST_INSERT_ID()
       </selectKey>
       insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
       <!-- 这里的#{}里面的内容不能乱写,他是User实体类中getXXX()方法的 XXX  此符号是通过get方法拿到值 -->
   </insert>

这里使用一个selectKey 标签来获取。

keyProperty 对应实体类中的属性名 。
keyColumn 对应数据库中的属性名 。
order 可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先生成主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后再执行 selectKey 中的语句。

1.3 更新操作

  • 在持久层中添加方法
    /**
     * 修改用户
     * @param user
     */
    void updateUser(User user);
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<update id="updateUser" parameterType="com.zut.domain.User">
        update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
 </update>
  • 在测试类中加入方法
    /**
     * 测试更新用户
     */
    @Test
    public void updateUser(){
        User u = new User();
        u.setId(41);
        u.setUsername("李老大");
        u.setBirthday(new Date());
        u.setSex("女");
        u.setAddress("北京市莲花大道");

        iUserDao.updateUser(u);
    }

1.4 删除操作

  • 在持久层中添加方法
/**
* 根据 id 删除用户
* @param userId
* @return
*/
int deleteUser(Integer userId);
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<!-- 删除用户 --> 
<delete id="deleteUser" parameterType="java.lang.Integer">
	delete from user where id = #{uid}
</delete>
  • 在测试类中加入方法
@Test
public void testDeleteUser() throws Exception {
	int res = userDao.deleteUser(52);
	System.out.println(res);
}

1.5用户模糊查询

  • 在持久层中添加方法
    /**
     * 根据姓名模糊查询多个用户
     * @param username
     * @return
     */
    List<User> listUserByName(String username);
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<select id="listUserByName" parameterType="java.lang.String" resultType="com.zut.domain.User">
        select * from user where username like #{name}
</select>

这里虽然返回结果为一个List,但resultType可以写为User,当有多个User时,Mybatis会自动帮我们封装为一个集合。

  • 在测试类中加入方法
	@Test
    public void listUserByName(){
        List<User> users = iUserDao.listUserByName("%王%");
        for (User user:users){
            System.out.println(user);
        }
    }

执行结果如下:
在这里插入图片描述

  • 我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标识%,配置文件中的#{name}也只是一个占位符,所以sql语句中为

另一种配置方式:

  • 修改用户的映射配置文件IUserDao.xml
<select id="listUserByName" parameterType="java.lang.String" resultType="com.zut.domain.User">
        select * from user where username like '%${value}%'
</select>
  • 修改测试方法
 	@Test
    public void listUserByName(){
        List<User> users = iUserDao.listUserByName("王");
        for (User user:users){
            System.out.println(user);
        }
    }

运行结果:
在这里插入图片描述

这里我们可以看到将以前的占位符改为了${value},者就是模糊查询的写法,注意!!! ${value}的写法是固定的,不能进行更改。

  • #{ } 与 ${ }的区别
  • #{ }表示一个占位符
  • ${ }表示拼接sql串

1.6 查询使用聚合函数

  • 在持久层中添加方法
    /**
     * 使用聚合函数查询用户总数
     * @return
     */
    int countUser();
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<select id="countUser" resultType="int">
        select count(id) from user
</select>
  • 在测试类中加入方法
/**
     * 测试查询用户总数
     */
    @Test
    public void countUser(){
        int count = iUserDao.countUser();
        System.out.println("用户记录总数为:" + count);
    }

2.Mybatis中一些参数的了解


2.1 parameterType配置参数

该属性之前已经简单介绍过,它的取值可以是基本类型、引用类型(例如String),还可以是实体类类型。这里说一下它的注意事项。

  • 基本类型和String我们可以直接写类型名称,也可以使用包名、类名的方式。
  • 实体类类型只能使用全限定类名。
  • 因为Mybatis它自动注册了基本类型和String类型的别名,所以使用时可以不写包名。
    而我们自己也可以为我们的实体类注册别名从而不再写包名,这个后面会说到。

2.2 传递pojo对象

  • 开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
  • 编写QueryVo
/**
 * 用于封装查询条件
 */
public class QueryVo {
    private User user;
    //如果还有其他的查询条件,就可以一并封住出来
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}
  • 在持久层添加方法
    /**
     * 根据查询条件模糊查询用户
     * @param vo
     * @return
     */
    List<User> listUsersByVo(QueryVo vo);
  • 在用户的映射配置文件IUserDao.xml 中进行配置。
<select id="listUsersByVo" parameterType="com.zut.domain.QueryVo" resultType="com.zut.domain.User">
      select * from user where username like #{user.username}
 </select>
  • 测试代码
/**
     * 测试根据Vo查询
     */
    @Test
    public void listUsersByVo(){
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%王%");

        vo.setUser(user);
        List<User> users  = iUserDao.listUsersByVo(vo);
        for (User user1:users){
            System.out.println(user1);
        }
    }

3.Mybatis输出结果的封装


3.1resultType配置结果类型

  • resultType和前面的parameterType类似,它支持基本类型和实体类类型。
  • 同时注册过别名的,也可以直接使用别名。

需要注意的是:
当类型为实体类型时,实体类的属性必须和查询语句中的列明保持一致。

  • 修改实体类
public class User implements Serializable {
	private Integer userId;
	private String userName;
	private Date userBirthday;
	private String userSex;
	private String userAddress;
  • 测试结果如下
    在这里插入图片描述

为什么userName有值呢?,这是因为Mysql在windows下不区分大小写。所以userName等同于username.

  • 为了解决实体类属性名和数据库列名不一致的情况,有如下的解决办法:
    1.在 SQL 语句中为所有列起别名,使别名与实体类属性名一致(执行效率相对高,开发效率低)
<select id="findAll" resultType="com.zut.domain.User">
    SELECT id AS userId, username AS userName, birthday AS userBirthday, sex AS userSex, address AS userAddress FROM user
</select>

2.使用resultMap标签建立查询的列名和实体类属性之间的映射关系(执行效率相对低,开发效率高)

<mapper namespace="com.zut.dao.IUserDao">
    <!-- 配置 resultMap ,完成实体类与数据库表的映射 -->
    <resultMap id="userMap" type="cn.ykf.pojo.User">
        <id property="userId" column="id" />
        <result property="userName" column="username"/>
        <result property="userBirthday" column="birthday"/>
        <result property="userAddress" column="address"/>
        <result property="userSex" column="sex"/>
    </resultMap>
    <!-- 配置查询所有用户 -->
    <select id="findAll" resultMap="userMap">
       SELECT * FROM user
    </select>
</mapper>

property代表实体类中的属性名称,column代表列名

4.SqlMapConfig.xml配置文件


4.1配置内容和顺序

注意:配置文件要严格遵守上图的顺序,比如typeAliases标签不能写到settings标签前面,否则会出错。

4.2properties标签

  • 在使用 properties 标签配置时,我们可以采用两种方式指定属性配置。

1.采用内部配置的方式

<?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>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/db_mybatis?characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="ljt074517"/>
    </properties>
    <!--配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务类型 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定映射文件 -->
    <mappers>
        <mapper resource="com/zut/dao/IUserDao.xml"/>
    </mappers>
</configuration>

2.使用resource属性引入外部配置文件(常用)

  • 在类路径下编写配置文件 jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=ljt074517
  • 修改Mybatis配置文件
<!-- 引入外部文件  -->
    <properties resource="jdbcConfig.properties"/>

    <!--配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务类型 -->
            <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>

4.3typeAliases标签(类型别名)

前面已经提到过别名这个概念,此标签的作用就是来配置别名

  • 当我们要给某个实体类指定别名时,就可以在 SqlMapConfig.xml 中去配置
    <!-- 配置别名 -->
    <typeAliases>
       <typeAlias type="com.zut.domain.User" alias="user"></typeAlias>
    </typeAliases>
  • type属性用于指定实体类的全限定类名,alias标签用于指定别名。
  • 也就是说当我们要用User这个实体类作为parameterType或resultType的类型时,可以直接写为user
  • 当我们需要给多个实体类起别名时,可以使用package标签
   <!-- 配置别名 -->
    <typeAliases>
        <package name="com.zut.domain"/>
    </typeAliases>

package 标签指定要配置别名的包,当指定之后,该包下的所有实体类都会注册别名,并且别名就是类名,不再区分大小写

  • package标签还有另外一个作用:注册指定包下的所有 mapper 接口
   <!-- 配置映射信息 -->
    <mappers>
        <package name="com.zut.dao"/>
    </mappers>
  • 这样配置后,我们就无需一个个的映射Mapper接口
  • 此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值