MyBatis入門主要講解了Mybatis的基本配置。在這些配置裏面需要注意一下問題:
-
持久層接口和持久層接口的映射配置文件必須在相同的包下。
-
持久層接口配置文件中的mapper標籤的namespace屬性取值必須是持久層就看的全限定類名。
-
SQL語句的配置標籤中的id屬性值必須和持久層接口的方法名相同。例如上面的<select>標籤中的id屬性值findAll和UserDao接口中的方法名findAll相同。
接着MyBatis入門繼續深入瞭解,在UserDao接口裏面加入根據Id查詢用戶的方法
package com.liang.dao;
import com.liang.domain.User;
import java.util.List;
public interface UserDao{
/**
* 查詢所有用戶
* @return
*/
List<User> findAll();
/**
* 根據id查詢用戶
* @param id
* @return
*/
User findById(int id);
}
同時需要在接口映射文件裏面添加相應的SQL語句:根據Id查詢用戶
<?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.liang.dao.UserDao">
<select id="findAll" resultType="com.liang.domain.User" >
select *from user;
</select>
<!--根據id查詢用戶-->
<select id="findById" resultType="com.liang.domain.User" parameterType="int">
select *from user where id= #{userID};
</select>
</mapper>
select標籤中需要掌握的是其屬性。
屬性名 | 屬性值 |
---|---|
resultType | 用於指定結果集的類型 |
parameterType | 用於指定傳入參數的類型 |
**SQL語句中使用的#{}字符:**代表佔位符,相當於使用jdbc的prepareStatement時候SQL語句傳入的?,都是用於執行語句時候替換爲實際的數據。
由於在MyBatis入門中通過main方法進行的測試的,這給後面的測試會帶來很多不便,因此我做了在下面做了修改,使用了測試類進行測試,修改代碼如下,並且加上了通過id查詢用戶的方法。
import com.liang.dao.UserDao;
import com.liang.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMyBatis {
private SqlSession sqlSession = null;
private InputStream inputStream = null;
private UserDao userDao = null;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.close();
inputStream.close();
}
/**
* 查詢所有用戶信息
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User user : users)
{
System.out.println(user.toString());
}
}
/**
* 通過ID查詢用戶
*/
@Test
public void testFindById(){
User user = userDao.findById(41);
System.out.println(user.toString());
}
}
實現保存用戶信息
繼續在持久層接口UserDao.java中添加保存方法。
/**
* 保存用戶
* @param user
*/
void saveUser(User user);
相應的在其對應的接口映射文件中添加SQL語句。
<!--注意此處傳入的參數類型是我們自定義的參數類型
相應的#{}佔位符寫入的內容,也應該是自定義類型的屬性名。
此處使用的都是apache提供的一種表達式語言 OGNL
全稱:Object Graphic Navigation Language(對象圖導航語言)
-->
<insert id="saveUser" parameterType="com.liang.domain.User">
insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex}, #{address});
</insert>
在測試類中添加測試方法。
@Test
public void testSaveUser()
{
User user = new User();
user.setUsername("娃哈啊");
user.setSex("女");
user.setBirthday(new Date());
user.setAddress("陝西");
userDao.saveUser(user);
System.out.println("保存完畢");
}
執行測試方法後,發現數據庫裏面並沒有添加成功,這裏和jdbc是相同的,在執行增刪改的時候要控制事務的提交,在Mybatis中通過SqlSession對象的commit()方法來提交事務。可以將提交事務的方法加入到 userDao.saveUser(user);後面,也可以加入到 @After裏面。
//在測試方法執行完成之後執行
@After
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
當添加提交方法後,在userDao.saveUser(user);後面打印用戶信息發現此時id值爲0,其實此處的id值是數據庫自增長實現的,因此需要在新增用戶後將自動增長的值進行獲取。修改接口映射文件如下:
<insert id="saveUser" parameterType="com.liang.domain.User">
<!--配置保存時,獲取插入的id
keyColumn: 數據庫表對應的字段
keyProperty: User對象的屬性
order: 執行順序
-->
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex}, #{address});
</insert>
修改後在userDao.saveUser(user);後面打印用戶信息發現id是我們需要的id.
添加更新用戶和以上步驟沒有任何區別。
在持久層添加更新方法:
/**
* 更新用戶
* @param user
*/
void updateUser(User user);
在持久層對應的映射文件添加SQL語句:
<!--更新用戶-->
<update id="updateUser" parameterType="com.liang.domain.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
在測試類中添加測試方法:
/**
* 更新用戶
*/
@Test
public void testUpdateUser()
{
User user = userDao.findById(70);
user.setUsername("wahaha");
userDao.updateUser(user);
System.out.println(user);
}
添加刪除用戶也是相同的三步。
在持久層添加刪除方法:
/**
* 通過用戶ID刪除用戶
* @param userId
*/
void deleteUser(int userId);
在相應的配置文件添加SQL語句:
<!--通過用戶id刪除用戶-->
<delete id="deleteUser">
delete from user where id= #{uid}
</delete>
在測試類中添加測試方法:
/**
* 通過用戶ID刪除用戶
*/
@Test
public void testDeleteUser()
{
userDao.deleteUser(70);
System.out.println("刪除成功");
}
兩種模糊查詢的方式
兩種方式和上面的一樣,都需要三步完成。
方式一
在持久層接口中添加模糊查詢的方法
/**
* 根據名稱模糊查詢
* @param name
* @return
*/
List<User>findByName(String name);
在映射文件中添加SQL語句
<!--根據名稱模糊查詢-->
<select id="findByName" parameterType="String" resultType="com.liang.domain.User">
select *from user where username like #{username}
</select>
添加測試方法
/**
* 根據名稱模糊查詢用戶
*/
@Test
public void testFindByName()
{
List<User> users = userDao.findByName("%小%");
for (User user : users)
{
System.out.println(user);
}
}
方式二
在持久層接口中添加模糊查詢的方法,這一步不做任何改變。
在映射文件中添加SQL語句
<!--根據名稱模糊查詢
需要注意問題:
1.將#{}佔位符改爲${value}
2.${value是固定寫法,不能該寫成其他}-->
<select id="findByName" parameterType="String" resultType="com.liang.domain.User">
select *from user where username like '%${value}%'
</select>
添加測試方法
/**
* 根據名稱模糊查詢用戶
*/
@Test
public void testFindByName()
{
List<User> users = userDao.findByName("小");
for (User user : users)
{
System.out.println(user);
}
}
以上兩種方式雖然執行結果相同,但是是有區別的,區別主要體現在執行SQL語句時。
#{}表示一個佔位符,相當於PreparedStatement,可以有效的防止SQL注入問題。而且#{}可以接收簡單類型的值和 POJO 屬性值。
{}也可以接收簡單類型值和 POJO 屬性值。如果parameterType傳遞耽擱簡單型參數${}括號中只能是value。
聚合函數的使用
在持久層接口中添加查詢總記錄條數的方法
/**
* 查詢總記錄條數
* @return
*/
int findTotal();
在映射文件中添加SQL語句
<!--查詢總記錄條數-->
<select id="findTotal" resultType="int">
select count(*) from user
</select>
添加測試方法
/**
* 查詢總記錄條數
*/
@Test
public void testFindTotal()
{
int res = userDao.findTotal();
System.out.println(res);
}