Mybatis基础使用三

1,311 阅读5分钟

4.6.1 parameterType

在映射文件中通过parameterType指定输入 参数的类型。

4.6.2 resultType

在映射文件中通过resultType指定输出结果的类型。

4.6.3 #{}和${}

#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。

如果接收简单类型,#{}中可以写成value或其它名称#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

{}表示一个拼接符号,会引用sql注入,所以不建议使用{}。 {}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,{}中只能写成value。 ${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。

4.6.4 selectOne和selectList

selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。

selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。

如果使用selectOne报错: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

mybatis开发dao的方式

##SqlSession ##

SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。

SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。

SqlSession最佳应用场合在方法体内,定义成局部变量使用。

编写dao方法

  • 程序员需要写dao接口和dao实现类。

  • 需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

      package com.ljl.dao;
      
      import com.ljl.po.User;
    
      import java.util.List;
    
      public interface UserDao {
       //根据用户id查询数据
    
    	public User FindById(int id);
    
    
    	//根据name查询一组数据
    
      public List<User> findByName();
    
      //添加数据到数据库
    
        public int insert(User user);
    
      	//根据id删除用户
       public void  delete(int id);
    
       //根据用户修改数据
    
       public void  update(User user) ;
    
      }
    

实现类

`

	public class UserImp implements UserDao {
	private SqlSessionFactory sqlSessionFactory;

public UserImp(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
}

@Override
public User FindById(int id) {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    User user = sqlSession.selectOne("test.findUserById", id);
    return user;
}

@Override
public List<User> findByName() {
    SqlSession session = sqlSessionFactory.openSession();
    List<User> result= session.selectList("test.findUserByname","李家浪");
    return result;
}

@Override
public int insert(User user) {
    SqlSession session = sqlSessionFactory.openSession();
    User user1=new User();
    user1.setUsername("增加22");
    user1.setBirthday(new java.sql.Date(20170128));
    user1.setAddress("北京22");
    user1.setSex("男222");
    session.insert("test.addUser",user);
    System.out.println(user.getId());
    //需要手动提交事务
    session.commit();
    session.close();
    return 0;
}

@Override
public void delete(int id) {
    SqlSession session = sqlSessionFactory.openSession();
    session.delete("test.deleteById",52);
    //需要手动提交事务
    session.commit();
    session.close();
}

@Override
public void update(User user) {
    SqlSession session = sqlSessionFactory.openSession();
    User user1=new User();
    user1.setId(52);
    user1.setUsername("修改name");
    user1.setAddress("西安啊啊啊啊啊");
    session.update("test.updatById",user);
    //需要手动提交事务
    session.commit();
    session.close();
}
}

`

编写单元测试类进行测试

  • 使用dao接口实现类存在大量模板方法,代码重复太多

  • 使用session的时候见statementId硬编码

  • session方法参数的类型是object,不利于发现错误

使用mapper代理的方法开发dao

  • 程序员还需要编写mapper.xml映射文件

  • 程序员只需要编写mapper接口(相当于dao接口)需遵循一些开发规范,mybatis可以自动生成mapper接口的实现类。

首先创建一个mapperJava文件

	public interface UserDaoMapper {


	}

其次创建一个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">
	<!--namespace命名空间:使用mapper代理方式开发,namespace有特殊重要的作用,是mapper接口的全路径
	-->
	<mapper namespace="com.ljl.mapperDao.UserDaoMapper">
          
    <select id="findUserById" parameterType="int" resultType="com.ljl.po.User">
		select * from user where id=#{id};
		</select>

</mapper>

在接口中写方法

	/** 方法名对应mapper.xml里面的id="findUserById"
 *  输入对象对于mapper.xml里面的parameterType="int"
 *  返回值对象的mapper.xml里面的resultType="com.ljl.po.User"
 * @param id
 * @return
 */
public User findUserById(int id);

基于mapper代理的方式,基本完成编写测试代码

	错误1  Type interface com.ljl.mapperDao.UserDaoMapper is not known to the MapperRegistry

这是因为我们新创建的usermapper.xml没有在batis-config中注册

	<mappers>
    <mapper resource="mapper/usermapper.xml"/>
    </mappers>

测试代码

public class UserDaoMapperTest {
SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
    InputStream inputStream= null;
    try {
        inputStream = Resources.getResourceAsStream("config/mybatis-config.xml");
    } catch (IOException e) {
        e.printStackTrace();
    }
    sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}

@Test
public void findUserById() {
    SqlSession session = sqlSessionFactory.openSession();
    //使用mapper代理生成mapper代理接口的实现类的对象
    UserDaoMapper usermaer = session.getMapper(UserDaoMapper.class);
    //调用方法
    User user = usermaer.findUserById(1);
    System.out.println(user);

}

}

5.3.6.1 代理对象内部调用selectOne或selectList

如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。

如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。

SqlMapConfig.xml

mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:

  • properties(属性)
  • settings(全局配置参数)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境集合属性对象)
  • environment(环境子属性对象)
  • transactionManager(事务管理)
  • dataSource(数据源)
  • mappers(映射器)

properties属性

将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。 在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。

将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb1
jdbc.username=root
jdbc.password=ljl123456

在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="config/jdbc.properties"></properties>
<environments default="development">
    <environment id="development">
        <!-- 使用JDBC的事务管理,事务控制由mybatis -->
        <transactionManager type="JDBC">
            <property name="..." value="..."/>
            <property name="" value=""/>
        </transactionManager>
        <!--数据库连接池,由mybatis控制-->
        <dataSource type="POOLED">
            <!--<property name="driver" value="com.mysql.jdbc.Driver"/>-->
            <!--<property name="url" value="jdbc:mysql://localhost:3306/mydb1"/>-->
            <!--<property name="username" value="root"/>-->
            <!--<property name="password" value="ljl123456"/>-->
            <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="config/sqlmap/user.xml"/>

    <mapper resource="mapper/usermapper.xml"/>
</mappers>
</configuration>

properties特性:

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

  • 在 properties 元素体内定义的属性首先被读取。
  • 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
  • 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

建议: 不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。 在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX