【MyBatis框架】MyBatis入门程序第二部分

我们通过写一个简单的MyBatis小项目来在实战中学习MyBatis,接着上一篇继续

我们开始实现需求中的添加和删除用户功能

(1)向数据库中添加用户数据
使用User.xml,加入添加用户的sql语句。

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 添加用户  
  2. parameterType:指定输入参数类型是pojo(包括用户信息)   
  3. #{}中指定POJO的属性名,接收到POJO对象的属性值,mybatis通过OGNL获取对象的属性  
  4. -->  
  5. <insert id="insertUser" parameterType="cn.edu.hpu.mybatis.PO.User">  
  6.     insert into user(username,birthday,sex,address) value(#{username}.#{birthday,jdbcType=DATE}.#{sex},#{address})  
  7. </insert>  

*注:在字段中有Date和DateTime类型,在插入数据时只要将实体的属性设置成Timestamp就会对应mysql的DateTime类型,Date会对应mysql的Date类型:
#{modified_date,jdbcType=TIMESTAMP}、#{date,jdbcType=DATE}。

测试方法:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //添加用户  
  2.     @Test  
  3.     public void insertUserTest(){  
  4.           
  5.         //mybatis配置文件  
  6.         String resource="SqlMapConfig.xml";  
  7.           
  8.         //将配置文件加载成流  
  9.         InputStream inputStream;  
  10.           
  11.         try {  
  12.               
  13.             inputStream = Resources.getResourceAsStream(resource);  
  14.             //创建会话工厂,传入mybatis配置文件的信息  
  15.             SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);  
  16.               
  17.             //通过工厂得到sqlSession  
  18.             sqlSession=sqlSessionFactory.openSession();  
  19.               
  20.             //插入用户对象  
  21.             User user=new User();  
  22.             user.setUsername("李云华");  
  23.             user.setBirthday(new Date());  
  24.             user.setSex("男");  
  25.             user.setAddress("云南大理");  
  26.             //通过SqlSession操作数据库  
  27.             //第一个参数:映射文件中的statement的Id,等于=namespace+"."+statement的Id  
  28.             //第二个参数:指定和映射文件所匹配的parameterType类型的参数  
  29.             //sqlSession.selectOne最终结果与你映射文件中所匹配的resultType类型  
  30.             sqlSession.insert("test.insertUser",user);  
  31.               
  32.             //提交事务  
  33.             sqlSession.commit();  
  34.               
  35.         } catch (IOException e) {  
  36.             e.printStackTrace();  
  37.         }finally{  
  38.             //释放资源  
  39.             sqlSession.close();  
  40.         }  
  41.           
  42.     }  

测试结果:
在数据库中插入了
李云华(String), 2015-06-07(Date), 男(String), 云南大理(String)

输出的日志信息:

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.  
  2. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  3. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  4. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  5. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  6. DEBUG [main] - Opening JDBC Connection  
  7. DEBUG [main] - Created connection 30685694.  
  8. DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  9. DEBUG [main] - ==>  Preparing: insert into user(username,birthday,sex,address) value(?,?,?,?)   
  10. DEBUG [main] - ==> Parameters: 李云华(String), 2015-06-07(Date), 男(String), 云南大理(String)  
  11. DEBUG [main] - <==    Updates: 1  
  12. DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  13. DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  14. DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  15. DEBUG [main] - Returned connection 30685694 to pool.  
(2)主键返回

a.自增主键的返回
mysql的自增主键,执行insert之前自动生成一个自增主键
通过mysql函数获取到刚插入记录的自增主键
LAST_INSERT_ID
(当插入一个数据后,立即用这个函数就会返回刚加的主键:SELECT LAST_INSERT_ID())

在刚刚的User.xml中这么写:

  1. <!-- 添加用户  
  2. parameterType:指定输入参数类型是pojo(包括用户信息)   
  3. #{}中指定POJO的属性名,接收到POJO对象的属性值,mybatis通过OGNL获取对象的属性  
  4. -->  
  5. <insert id="insertUser" parameterType="cn.edu.hpu.mybatis.PO.User">  
  6.     <!-- 将插入数据的主键返回,返回到user对象中。  
  7.     SELECT_INSERT_ID():得到刚insert进去的主键值,只适用于自增主键   
  8.     KeyProperty:将查询到主键值设置到parameterType指定对象的哪个属性。  
  9.     order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序  
  10.     -->  
  11.     <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">  
  12.         SELECT LAST_INSERT_ID()  
  13.     </selectKey>  
  14.     insert into user(username,birthday,sex,address) value(#{username},#{birthday,jdbcType=DATE},#{sex},#{address})  
  15. </insert>  

我们在刚刚的方法后面输出user的ID

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //插入用户对象  
  2. User user=new User();  
  3. user.setUsername("李云华");  
  4. user.setBirthday(new Date());  
  5. user.setSex("男");  
  6. user.setAddress("云南大理");  
  7. //通过SqlSession操作数据库  
  8. //第一个参数:映射文件中的statement的Id,等于=namespace+"."+statement的Id  
  9. //第二个参数:指定和映射文件所匹配的parameterType类型的参数  
  10. //sqlSession.selectOne最终结果与你映射文件中所匹配的resultType类型  
  11. sqlSession.insert("test.insertUser",user);  
  12.               
  13. //提交事务  
  14. sqlSession.commit();  
  15.               
  16. System.out.println(user.getId());  

结果:6
为啥能得到,就是在配置文件里设置了当insert完成之后就把id取出来存到user对象中

b.非自增主键的返回
使用mysql的uuid()函数生成主键,需要修改表中id字段类型为string,长度设置成35位。

执行思路:
先通过uuid()查询到主键,将主键输入到sql语句中。

执行uuid()语句顺序相对于insert语句之前执行。

在刚刚的User.xml中这么写:

  1. <!-- 使用MySql的UUID来生成主键  
  2.         执行过程:  
  3.         首先通过uuid()得到主键,将主键设置到user对象的id属性中  
  4.         其次在insert执行时,从user对象中取出id属性值 -->  
  5.         <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">  
  6.             SELECT uuid()  
  7.         </selectKey>  
  8.         insert into user(id,birthday,sex,address) value(#{id},#{birthday,jdbcType=DATE},#{sex},#{address})  
  9.   
  10. 如果使用的数据库是oracle那么通过oracle的序列生成主键写法:  
  11. <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">  
  12.             SELECT 序列名.nextval()  
  13. </selectKey>  
  14. insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday,jdbcType=DATE},#{sex},#{address})  

测试略

(3)删除和更新用户
映射文件User.xml中添加的语句:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 删除用户 -->  
  2. <delete id="deleteUser" parameterType="java.lang.Integer">  
  3.     delete from user where id=#{id}  
  4. </delete>  
  5.       
  6. <!-- 更新用户   
  7. 分析:  
  8. 需要传入用户的id,需要传入用户的更新信息.  
  9. parameterType指定user对象,包括id和更新信息(注意:id必须存在)  
  10. #{id}:从输入user对象中获取id属性值-->  
  11. <update id="updateUser" parameterType="cn.edu.hpu.mybatis.PO.User">  
  12.     update user set username=#{username},birthday=#{birthday,jdbcType=DATE},sex=#{sex},address=#{address}     
  13.         where id=#{id}  
  14. </update>  

测试代码:
删除测试代码:

  1. //删除用户  
  2.     @Test  
  3.     public void deleteUserTest(){  
  4.           
  5.         //mybatis配置文件  
  6.         String resource="SqlMapConfig.xml";  
  7.           
  8.         //将配置文件加载成流  
  9.         InputStream inputStream;  
  10.           
  11.         try {  
  12.               
  13.             inputStream = Resources.getResourceAsStream(resource);  
  14.             //创建会话工厂,传入mybatis配置文件的信息  
  15.             SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);  
  16.               
  17.             //通过工厂得到sqlSession  
  18.             sqlSession=sqlSessionFactory.openSession();  
  19.               
  20.             //传入id删除用户  
  21.             sqlSession.delete("test.deleteUser",6);  
  22.               
  23.             //提交事务  
  24.             sqlSession.commit();  
  25.               
  26.         } catch (IOException e) {  
  27.             e.printStackTrace();  
  28.         }finally{  
  29.             //释放资源  
  30.             sqlSession.close();  
  31.         }  
  32.           
  33.     }  
  34.       

测试结果:从数据库删除了id为6的数据

输出日志:

  1. DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.  
  2. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  3. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  4. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  5. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  6. DEBUG [main] - Opening JDBC Connection  
  7. DEBUG [main] - Created connection 30685694.  
  8. DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  9. DEBUG [main] - ==>  Preparing: delete from user where id=?   
  10. DEBUG [main] - ==> Parameters: 6(Integer)  
  11. DEBUG [main] - <==    Updates: 1  
  12. DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  13. DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  14. DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  15. DEBUG [main] - Returned connection 30685694 to pool.

更新测试代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //更新用户  
  2. @Test  
  3. public void updateUserTest(){  
  4.       
  5.     //mybatis配置文件  
  6.     String resource="SqlMapConfig.xml";  
  7.       
  8.     //将配置文件加载成流  
  9.     InputStream inputStream;  
  10.       
  11.     try {  
  12.           
  13.         inputStream = Resources.getResourceAsStream(resource);  
  14.         //创建会话工厂,传入mybatis配置文件的信息  
  15.         SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);  
  16.           
  17.         //通过工厂得到sqlSession  
  18.         sqlSession=sqlSessionFactory.openSession();  
  19.           
  20.         //更新用户信息(更改id=5的用户数据)  
  21.         User user=new User();  
  22.         user.setId(5);  
  23.         user.setUsername("刘三姐");  
  24.         user.setBirthday(new Date());  
  25.         user.setSex("女");  
  26.         user.setAddress("云南大理");  
  27.         sqlSession.update("test.updateUser",user);  
  28.           
  29.         //提交事务  
  30.         sqlSession.commit();  
  31.           
  32.     } catch (IOException e) {  
  33.         e.printStackTrace();  
  34.     }finally{  
  35.         //释放资源  
  36.         sqlSession.close();  
  37.     }  
  38.       
  39. }  

测试结果:
id=5的数据被更新

输出日志:
[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.  
  2. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  3. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  4. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  5. DEBUG [main] - PooledDataSource forcefully closed/removed all connections.  
  6. DEBUG [main] - Opening JDBC Connection  
  7. DEBUG [main] - Created connection 30685694.  
  8. DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  9. DEBUG [main] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?   
  10. DEBUG [main] - ==> Parameters: 刘三姐(String), 2015-06-07(Date), 女(String), 云南大理(String), 5(Integer)  
  11. DEBUG [main] - <==    Updates: 1  
  12. DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  13. DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  14. DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@1d439fe]  
  15. DEBUG [main] - Returned connection 30685694 to pool.  

小结:
a.parameterType
在映射文件中通过parameterType指定输入 参数的类型。

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

c.#{}和${}

#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。


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

d.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



最后来说说hibernate与mybatis,大家如果用过hibernate,刚学mybatis就会很疑惑,mybatis的执行效率并不比hibernate高多少,而且还要多写sql语句,为什么要用它呢?下面来看一下它们的区别,你就会明白mybatis的存在是有一定道理的

看看 mybatis和hibernate本质区别 和应用场景:

hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
应用场景:
适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。

mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
应用场景:
适用与需求变化较多的项目,比如:互联网项目。

企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值