本次全部学习内容MyBatisLearning

 
查:
根据id查询用户信息,得到一个用户信息
 
在User.xml文件中添加代码:
 <mapper namespace="test">
    <!-- 配置很多的sql语句 -->

     <!-- 查询标签 -->
     <!-- id用于唯一标识这个sql查询 -->
     <!-- #{} 标识占位符 -->
     <!-- parameterType:指定输入参数的类型: -->
     <!-- #{id}:接受输入的参数,id表示输入的参数,参数名就是id,如果输入参数是简单的类型,#{}中的参数可以是任意字符 -->
     <!-- resultType:输出结果的类型 所映射的java 类型对象,单挑记录所映射成的java对象-->

     <select id="findUserByID" parameterType="int" resultType="com.MrChengs.po.User">
           select * from user where id=#{id}
     </select>
</mapper>
 
在测试代码中test.java:
//根据id查询用户信息,得到一个用户信息
     @Test
     public void findUserById() throws IOException{

           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);

           //创建会话工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

           //通过工程得到Session
           SqlSession session = sessionFactory.openSession();

           //通过SqlSession操作数据库
           //session.selectOne(arg0, arg1)
           //第一个参数:映射文件statement的id,等于 namespace.statement
           //第二个参数:指映射文件的中的parameType的类型参数

           User user = session.selectOne("test.findUserByID", 10);
           System.out.println(user);
           //关闭资源
           session.close();
     }
这里的代码使用try{}finally{} 和jdbc类似,暂时没有使用!
 
控制台的结果:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 733957003.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b]
DEBUG [main] - ==>  Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 10(Integer)
DEBUG [main] - <==      Total: 1
User [id=10, username=张三, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=北京市]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2bbf4b8b]
DEBUG [main] - Returned connection 733957003 to pool.
根据用户名称来模糊查询用户信息:
在User,xml文件中添加代码:
     <!-- 模糊查询 -->
     <!-- resultType:指定单挑记录所映射的类型 -->
     <select id="findByName" parameterType="java.lang.String" resultType="com.MrChengs.po.User" >
           select * from user where username Like #{username}
     </select>
 
其余不变去测试代码中
在测试代码中test.java:
//根据用户名称来模糊查询用户
     @Test
public void findUserByName() throws IOException{

           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);

           //创建会话工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

           //通过工程得到Session
           SqlSession session = sessionFactory.openSession();

           //通过SqlSession操作数据库
           //selectList(String arg0, Object arg1)
           //list中的user和映射文件中的resultType所指类型一直
           //百分号不能忘记添加
           List<User> users = session.selectList("test.findByName", "%小明%");
           for(User user : users){
                System.out.println(user);
           }
           //关闭资源
           session.close();
     }
     

注意红色标记的部分。

 
 
思考:我们可不可以不在测试类中添加百分号?
 
我们这本此程序代码的基础上进行改进:
在User,xml文件中:
<!-- 模糊查询 -->
     <!-- resultType:指定单挑记录所映射的类型 -->

     <!-- ${} :表示拼接sql串,将接收的参数的内容不加任何修饰的拼接在sql中 -->
     <!-- 使用 ${ } 拼接sql,容易sql注入 -->
     <!-- ${}  接受参数的内容,如果传入类型是简单类型  ${} 只能使用value -->
     <select id="findByName" parameterType="java.lang.String" resultType="com.MrChengs.po.User" >
           select * from user where username Like '%${value}%'
     </select>
在这里测试时,'%${value}%',其余字符得不到结果,只能使用value
 
测试代码test.java中:
//根据用户名称来模糊查询用户
     @Test
public void findUserByName() throws IOException{

           //配置文件的
           String resource = "SqlMapConfig.xml";
           //得到配置文件流
           InputStream inputStream = Resources.getResourceAsStream(resource);

           //创建会话工程
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

           //通过工程得到Session
           SqlSession session = sessionFactory.openSession();

           //通过SqlSession操作数据库
           //selectList(String arg0, Object arg1)
           //list中的user和映射文件中的resultType所指类型一直
           List<User> users = session.selectList("test.findByName", "小明");
           for(User user : users){
                System.out.println(user);
           }

此时此刻,没有使用 %

结果:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 213193302.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - ==>  Preparing: select * from user where username Like '%小明%'
DEBUG [main] - ==> Parameters:
DEBUG [main] - <==      Total: 3
User [id=16, username=张小明, birthday=null, sex=1, address=河南郑州]
User [id=22, username=陈小明, birthday=null, sex=1, address=河南郑州]
User [id=25, username=陈小明, birthday=null, sex=1, address=河南郑州]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
DEBUG [main] - Returned connection 213193302 to pool.
 
此时是直接拼串,没有占位符,这种方法的使用,容易被注入!
 
查询小结:
1.
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
2.
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
selectList可以查询一条或多条记录。
3.
#{}  & ${} 
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
 
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value
 
----------------------------------------------------华丽的分割线----------------------------------------------------
 
添加用户:
在在User,xml文件中:
主键id是自增的,此时也可以省略主键
    <!-- 添加用户 -->
     <!-- parameterType:指定输入的参数类型是pojo(包括用户信息) -->
     <!-- #{} 中指定pojo的属性名,接收到的pojo对象的属性值,mybatis通过OGNL获取对象的属性值 -->
     <insert id="addUser" parameterType="com.MrChengs.po.User">
           insert into user(id,username,birthday,sex,address)
            value(#{id},#{username},#{birthday},#{sex},#{address})
     </insert>
 
在测试类test.java:
//添加用户
     @Test
public void addUser() throws IOException{
           String resource = "SqlMapConfig.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
           SqlSession session = sessionFactory.openSession();

           //添加的用户信息
           User user = new User();
           user.setUsername("MrCheng");
           user.setSex(1);
           user.setBirthday(new Date());
           user.setAddress("北京");

           session.insert("test.addUser", user);

           //需要提交事物
           session.commit();
           //关闭会话
           session.close();
     }

查看结果:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1384722895.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - ==>  Preparing: insert into user(id,username,birthday,sex,address) value(?,?,?,?,?)
DEBUG [main] - ==> Parameters: 0(Integer), MrCheng(String), 2018-10-05 13:09:06.928(Timestamp), 1(Integer), 北京(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@528931cf]
DEBUG [main] - Returned connection 1384722895 to pool.

假设我们此时在添加用户的同时得到主键值:

自增主键返回:
mysql自增主键,执行insert提交之前自动生成一个主键 
通过mysql函数获取自增主键
对之前的代码进行修改
User.xml文件中:

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

     <!-- 添加用户 -->
     <!-- parameterType:指定输入的参数类型是pojo(包括用户信息) -->
     <!-- #{} 中指定pojo的属性名,接收到的pojo对象的属性值,mybatis通过OGNL获取对象的属性值 -->
     <insert id="addUser" parameterType="com.MrChengs.po.User">

           <!-- 将插入的数据主键返回,返回到user对象中 -->
           <!-- SELECT LAST_INSERT_ID():得到insert插入后得到的主键值 -->
           <!-- keyProperty:将查询到的主键设置到parameterType指定对象的属性中 -->
           <!-- order:执行顺序,相对比插入insert来说 -->
           <!-- resultType:指定结果的类型 -->
           <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
                SELECT LAST_INSERT_ID()
           </selectKey>

           insert into user(id,username,birthday,sex,address)
            value(#{id},#{username},#{birthday},#{sex},#{address})
     </insert>
 
测试类test.java中:
@Test
public void addUser() throws IOException{
           String resource = "SqlMapConfig.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
           SqlSession session = sessionFactory.openSession();
           User user = new User();
           user.setUsername("MrCheng");
           user.setSex(1);
           user.setBirthday(new Date());
           user.setAddress("北京");

           session.insert("test.addUser", user);

           System.out.println(user.getId());
           //需要提交事物
           session.commit();


           //关闭会话
           session.close();
     }

结果:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: insert into user(id,username,birthday,sex,address) value(?,?,?,?,?)
DEBUG [main] - ==> Parameters: 0(Integer), MrCheng(String), 2018-10-05 14:11:48.735(Timestamp), 1(Integer), 北京(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - ==>  Preparing: SELECT LAST_INSERT_ID()
DEBUG [main] - ==> Parameters:
DEBUG [main] - <==      Total: 1
28
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Returned connection 22429093 to pool.
 
非自增主键的返回:
使用mysql的uuid()函数生成逐渐,需要修改表中的id为String,长度设置为35位
需要增加通过select uuid()得到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”

  

----------------------------------------------------华丽的分割线----------------------------------------------------

删除用户:

映射文件中:
 
User.xml文件:
<!-- 删除用户 -->
     <!-- 根据id删除 -->
     <delete id="deleteUser" parameterType="java.lang.Integer">
           delete from user where id=#{id}
     </delete>

测试类:

    //删除用户
    @Test
     public void deleteUser() throws IOException{

                String resource = "SqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

                SqlSession session = sessionFactory.openSession();

                session.delete("test.deleteUser", 28);
                //需要提交事物
                session.commit();
                //关闭会话
                session.close();
           }

控制台:

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: delete from user where id=?
DEBUG [main] - ==> Parameters: 28(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - Returned connection 22429093 to pool.

----------------------------------------------------华丽的分割线----------------------------------------------------

更新数据:

User.xml

    <!-- 更新用户 -->
     <!-- 根据id更新用户 -->
     <!-- parameterType:指定user对象,包括id更新信息,注意id必须存在 -->
     <update id="updateUser" parameterType="com.MrChengs.po.User">
           update user set username=#{username},sex=#{sex} where id = #{id}

     </update>

测试类:

          //更新
           @Test
           public void updateUser() throws IOException{
                String resource = "SqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                SqlSession session = sessionFactory.openSession();
                User user = new User();
                user.setUsername("MrChegns");
                user.setSex(2);
                user.setId(27);
                session.update("test.updateUser", user);
                //需要提交事物
                session.commit();

                //关闭会话
                session.close();
           }
注意:id必须要上进行设置。
控制台:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 22429093.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
DEBUG [main] - ==>  Preparing: update user set username=?,sex=? where id = ?
DEBUG [main] - ==> Parameters: MrChegns(String), 2(Integer), 27(Integer)
DEBUG [main] - <==    Updates: 1

 Mybatis解决jdbc编程的问题

1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。

2、 Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4、 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

当你看到这里,基本入门程序已经讲解完了!!!

10-05 20:35