該功能還可以通過 <insert/> 的 useGeneratedKeys / keyProperty 兩個屬性合作完成, 詳見 MyBatis文檔 .
</div>
Update
<update id="updateUserById" parameterType="com.fq.domain.User">
UPDATE user SET name = #{name}, password = #{password} WHERE id = #{id};
</update>
@Test
public void updateUserById() {
try (SqlSession session = factory.openSession(true)) {
session.update("namespace.updateUserById",
new User(1, "feiqing", "ICy5YqxZB1uWSwcVLSNLcA=="));
}
}
Delete
<delete id="deleteUserById" parameterType="java.lang.Integer">
DELETE FROM user WHERE id = #{id};
</delete>
@Test
public void deleteUserById() {
try (SqlSession session = factory.openSession(true)) {
session.delete("namespace.deleteUserById", 51615);
}
}
小結
附: 最好在pom.xml中添加一個日志系統實現(logback/log4j), 這樣會在調試程序時打印日志信息,便于查錯, 以logback為例:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<configuration>
<property name="logRoot" value="/data/logs"/>
<property name="pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logRoot}/common-server.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration></pre>
其他關于MyBatis日志的詳細信息可參考 MyBatis文檔日志部分 .
</div>
DAO開發
使用MyBatis開發DAO有兩個方法, 原始DAO開發 與 Mapper映射DAO開發 .
原始DAO開發
原始DAO開發需要開發人員編寫 DAO接口 與 DAO實現 ,如根據ID查詢用戶信息:
<select id="selectUserById" parameterType="java.lang.Integer" resultType="com.fq.domain.User">
SELECT * FROM user WHERE id = #{id};
</select>
/** * @author jifang * @since 16/2/22 上午10:20. */
public interface UserDAO {
User selectUserById(Integer id) throws Exception;
}
public class UserDAOImpl implements UserDAO {
private SqlSessionFactory factory;
public UserDAOImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public User selectUserById(Integer id) throws Exception {
SqlSession session = factory.openSession();
User user = session.selectOne("namespace.selectUserById", id);
session.close();
return user;
}
}</pre>
public class MyBatisClient {
@Test
public void originalClient() throws Exception {
UserDAO dao = new UserDAOImpl(new SqlSessionFactoryBuilder().
build(ClassLoader.getSystemResourceAsStream("mybatis/mybatis-configuration.xml")));
User user = dao.selectUserById(1);
System.out.println(user);
}
}</pre>
-
原始DAO開發中存在的問題:
1) DAO實現方法體中存在很多過程性代碼.
2) 調用 SqlSession 的方法( select / insert / update )需要指定 Statement 的id,存在硬編碼,不利于代碼維護.
</ul>
Mapper映射開發
mapper映射開發方法只需編寫DAO接口,MyBatis根據接口定義與mapper文件中的SQL語句動態創建接口實現.
<?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.fq.mybatis.UserDAO">
<select id="selectUserById" parameterType="java.lang.Integer" resultType="com.fq.domain.User">
SELECT * FROM user WHERE id = #{id};
</select>
</mapper>
注意: 此時 namespace 必須與 UserDAO 接口的全限定名相同.
</div>
- UserDAO接口與前面相同, 但不再使用 UserDAOImpl
- Client
/* @author jifang @since 16/2/22 下午2:57. /
public class MyBatisClient {
private SqlSession session;
private SqlSessionFactory factory;
@Before
public void setUp() {
factory = new SqlSessionFactoryBuilder().
build(ClassLoader.getSystemResourceAsStream("mybatis/mybatis-configuration.xml"));
session = factory.openSession();
}
@Test
public void mapperClient() throws Exception {
UserDAO dao = session.getMapper(UserDAO.class);
User user = dao.selectUserById(1);
System.out.println(user);
}
@After
public void tearDown() {
session.close();
}
}</pre>
-
mapper映射開發方法需要遵循以下規范:
<ol>
<li>mapper文件中的namespace與DAO接口的全限定名相同;</li>
<li> mapper文件中的 <em>Statement</em> 的id與DAO接口方法名相同; </li>
<li> mapper文件中的 <em>Statement</em> 的 parameterType / resultType 與DAO方法的入參/回參類型相同. </li>
</ol>
</li>
</ul>
</div>
Mapper映射
mapper映射文件(如UserDAO.xml)主要作用是定義SQL語句(每個SQL是一個 Statement ),是MyBatis的核心.
MyBatis官方推薦使用mapper映射的方法來開發DAO,因此我們以后就不再過多介紹原始DAO的開發.
輸入映射
多個形參
傳遞簡單類型前面示例已經使用過,在此就不再贅述.當需要傳遞多個形參時,不再需要設置 parameterType 參數:
<update id="updateUserById">
UPDATE user SET name = #{1}, password = #{2} WHERE id = #{0};
</update>
void updateUserById(Integer id, String name, String password) throws Exception;
傳入PO
MyBatis使用 OGNL 表達式解析對象屬性值:
<select id="selectUserByNamePassword" parameterType="com.fq.domain.User" resultType="com.fq.domain.User">
SELECT *
FROM user
WHERE name = #{name} AND password = #{password};
</select>
User selectUserByNamePassword(User user) throws Exception;
傳入Map
<select id="selectUserByMap" parameterType="java.util.Map" resultType="com.fq.domain.User">
SELECT *
FROM user
WHERE name = #{name} AND password = #{password};
</select>
#{} 花括號內對應 Map 的 key .
</div>
User selectUserByMap(Map<String, Object> map) throws Exception;
輸出映射
輸出簡單類型
<select id="selectUserCount" parameterType="java.lang.String" resultType="java.lang.Integer">
SELECT count(*)
FROM user
WHERE name LIKE '%${value}%';
</select>
Integer selectUserCount(String name) throws Exception;
返回簡單類型必須保證 查詢結果只有一行記錄 ,最終將第一個字段的值轉換為輸出類型.
</div>
輸出PO對象/列表
輸出Map
輸出PO對象完全可以改用 Map 輸出, 字段名作key,字段值作value .
<select id="selectUserLikeName" resultType="java.util.Map">
SELECT *
FROM user
WHERE name LIKE '%${value}%';
</select>
List<Map<String, Object>> selectUserLikeName(String name) throws Exception;
resultMap
resultType 可將查詢結果映射為PO,但前提是 PO屬性名 與 SQL字段名 必須一致,如不一致,則可通過 resultMap 作對應映射:
<resultMap id="userMap" type="com.fq.domain.User">
<id column="user_id" property="id"/>
<result column="user_name" property="name"/>
<result column="user_password" property="password"/>
</resultMap>
<select id="selectUserByName" parameterType="java.lang.String" resultMap="userMap">
SELECT
id user_id,
name user_name,
password user_password
FROM user
WHERE name = #{name};
</select></pre>
屬性 |
<th align="center">描述</th>
</tr>
</thead>
<id/> |
<td align="center">表示查詢結果集的唯一標識;</td>
</tr>
<result/> |
表示普通結果,即PO屬性; |
column |
表示SQL查詢出來的字段名, |
property |
表示PO屬性. |
</tbody>
</table>