MyBatis实践之DAO与Mapper

MyBatis简介

MyBatis前身是iBatis,是一个基于Java的数据持久层/对象关系映射(ORM)框架.

MyBatis是对JDBC的封装,使开发人员只需关注SQL本身,而不需花费过多的精力去处理如注册驱动、设置参数、创建Connection/Statement、解析结果集等JDBC过程性代码.MyBatis基于XML/注解的方式配置Statement,执行SQL,并将执行结果映射成Java对象, 大大降低了数据库开发的难度.

MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
– MyBatis项目地址/在线文档.

初识MyBatis

使用MyBatis需要在pom.xml中添加如下依赖:

<code class="hljs xml"><dependency>
<groupid>org.mybatis</groupid>
<artifactid>mybatis</artifactid>
<version>3.3.0</version>
</dependency>
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
<version>5.1.36</version>
</dependency></code>

Select

配置mybatis/mybatis-configuration.xml

作为MyBatis的全局配置文件,其配置了MyBatis的运行环境信息(如数据源/mapper文件等).

<code class="hljs xml"><code class="hljs xml"><!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%2D%2D%3E-->
<configuration>
<environments default="development">
<environment id="development">
<!--{cke_protected}{C}%3C!%2D%2D%20%E9%85%8D%E7%BD%AEJDBC%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%2D%2D%3E-->
<transactionmanager type="JDBC">
<!--{cke_protected}{C}%3C!%2D%2D%20%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E6%BA%90%2D%2D%3E-->
<datasource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver">
<property name="url" value="jdbc:mysql://host:port/db?characterEncoding=utf-8">
<property name="username" value="username">
<property name="password" value="password">
</property></property></property></property></datasource>
</transactionmanager></environment>
</environments>
<!--{cke_protected}{C}%3C!%2D%2D%20%E5%8A%A0%E8%BD%BDmapper%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6%20%2D%2D%3E-->
<mappers>
<mapper resource="mybatis/mapper/UserDAO.xml">
</mapper></mappers>
</configuration></code></code>

书写UserDAO(mapper映射)

最为MyBatis最核心的部分,配置了操作数据库的SQL语句:

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%2D%2D%3E-->
<mapper namespace="namespace">
<select id="selectUserById" parametertype="java.lang.Integer" resulttype="com.fq.domain.User">
SELECT * FROM user WHERE id = #{id};
</select>
<select id="selectUserByName" parametertype="java.lang.String" resulttype="com.fq.domain.User">
SELECT * FROM user WHERE name LIKE '%${value}%';
</select>
</mapper></code></code></code>

属性 描述

namespace 命名空间,用于隔离SQL语句

parameterType 定义SQL输入映射类型,MyBatis通过OGNL从输入对象中获取参数传入SQL语句.

resultType 定义SQL输出映射类型,MyBatis将SQL查询结果的一行记录映射为resultType指定的类型.

mapper映射文件名有UserDAO.xml/UserMapper.xml/User.xml等几种形式, 其一般存放在与mybatis-configuration.xml同级的mapper目录下,由于其主要作用为定义SQL语句与映射关系, 因此一般统称为mapper映射文件.

定义PO类

PO类主要作用为SQL(输入/输出)映射,通常与数据库表对应:

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java">/**
* @author jifang
* @since 15/12/31 下午2:27.
*/
public class User {
private Integer id;
private String name;
private String password;
public User() {
}
public User(Integer id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}</code></code></code></code>

UserDAO(Java对象)

获得SqlSession,执行SQL语句, 得到映射结果:

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java">/**
* @author jifang
* @since 16/2/24 下午6:15.
*/
public class UserDAO {
private SqlSessionFactory factory;
@Before
public void setUp() throws IOException {
String resource = "mybatis/mybatis-configuration.xml";
factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
}
@Test
public void selectUserById() {
try (SqlSession session = factory.openSession()) {
User user = session.selectOne("namespace.selectUserById", 1);
System.out.println(user);
}
}
@Test
public void selectUserByName() {
try (SqlSession session = factory.openSession()) {
List<user> users = session.selectList("namespace.selectUserByName", "student");
for (User user : users) {
System.out.println(user);
}
}
}
}</user></code></code></code></code></code>

Insert

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><insert id="insertUser" parametertype="com.fq.domain.User">
INSERT INTO user(name, password) VALUES(#{name}, #{password});
</insert></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java">@Test
public void insertUser() {
try (SqlSession session = factory.openSession()) {
User user = new User();
user.setName("new_name1");
user.setPassword("new_password");
session.insert("namespace.insertUser", user);
session.commit();
}
}</code></code></code></code></code></code></code>

自增主键返回

修改mapper文件,添加,可以将MySQL的自增主键(即刚刚插入数据时生成的ID)返回:

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><insert id="insertUser" parametertype="com.fq.domain.User">
<selectkey keyproperty="id" order="AFTER" resulttype="java.lang.Integer">
SELECT LAST_INSERT_ID();
</selectkey>
INSERT INTO user(name, password) VALUES(#{name}, #{password});
</insert></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs">@Test
public void insertUser() {
try (SqlSession session = factory.openSession()) {
System.out.println(session);
User user = new User(null, "new_name", "new_password");
session.insert("namespace.insertUser", user);
// 需要在commit之后才能获得自增主键
session.commit();
System.out.println(user.getId());
}
}</code></code></code></code></code></code></code></code></code>

该功能还可以通过的useGeneratedKeys/keyProperty两个属性合作完成, 详见MyBatis文档.

Update

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><update id="updateUserById" parametertype="com.fq.domain.User">
UPDATE user SET name = #{name}, password = #{password} WHERE id = #{id};
</update></code></code></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java">@Test
public void updateUserById() {
try (SqlSession session = factory.openSession(true)) {
session.update("namespace.updateUserById",
new User(1, "feiqing", "ICy5YqxZB1uWSwcVLSNLcA=="));
}
}</code></code></code></code></code></code></code></code></code></code></code>

Delete

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><delete id="deleteUserById" parametertype="java.lang.Integer">
DELETE FROM user WHERE id = #{id};
</delete></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java">@Test
public void deleteUserById() {
try (SqlSession session = factory.openSession(true)) {
session.delete("namespace.deleteUserById", 51615);
}
}</code></code></code></code></code></code></code></code></code></code></code></code></code>

小结

#{}/${}

#{}: 表示一个占位符号,实现向PreparedStatement占位符中设置值(#{}表示一个占位符?),自动进行Java类型到JDBC类型的转换(因此#{}可以有效防止SQL注入).#{}可以接收简单类型或PO属性值,如果parameterType传输的是单个简单类型值,#{}花括号中可以是value或其它名称. ${}: 表示拼接SQL串,通过${}可将parameterType内容拼接在SQL中而不进行JDBC类型转换,${}可以接收简单类型或PO属性值,如果parameterType传输的是单个简单类型值,${}花括号中只能是value.

虽然${}不能防止SQL注入,但有时${}会非常方便(如order by排序,需要将列名通过参数传入SQL,则用ORDER BY ${column},使用#{}则无法实现此功能(详见JDBC基础关于PreparedStatement的讨论).

SqlSession

提供操作数据库的方法(如:selectOne/selectList).但SqlSession是线程不安全的,因此最好将其定义成局部变量使用.

MyBatis优点(与JDBC相比)

SQL写在Java代码中导致不易维护, 而MyBatis将SQL写在mapper中,XML与Java代码分离. 向SQL语句传参繁琐(如:SQL的where条件不一,SQL数据类型与Java不同),MyBatis通过parameterType自动将Java对象映射至SQL语句. 结果集解析麻烦(SQL变化导致解析代码变化,SQL数据类型与Java不同),MyBatis通过resultType自动将SQL执行结果映射成Java对象.
附: 最好在pom.xml中添加一个日志系统实现(logback/log4j), 这样会在调试程序时打印日志信息,便于查错, 以logback为例:

pom.xml

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><dependency>
<groupid>ch.qos.logback</groupid>
logback-classic</artifactid>
<version>1.1.2</version>
</dependency></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

logback.xml

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><configuration>

<property name="logRoot" value="/data/logs">
<property name="pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n">
<appender class="ch.qos.logback.core.ConsoleAppender" name="STDOUT">
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE">
<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">
</appender-ref></appender-ref></root>
</property></property></configuration></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

其他关于MyBatis日志的详细信息可参考MyBatis文档日志部分.

DAO开发

使用MyBatis开发DAO有两个方法,原始DAO开发与Mapper映射DAO开发.

原始DAO开发
原始DAO开发需要开发人员编写DAO接口与DAO实现,如根据ID查询用户信息:

mapper(同前)

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><select id="selectUserById" parametertype="java.lang.Integer" resulttype="com.fq.domain.User">
SELECT * FROM user WHERE id = #{id};
</select></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO接口

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java">/**
* @author jifang
* @since 16/2/22 上午10:20.
*/
public interface UserDAO {
User selectUserById(Integer id) throws Exception;
}</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO实现

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java">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;
}
}</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

Client

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs">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);
}
}</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

原始DAO开发中存在的问题:

1) DAO实现方法体中存在很多过程性代码.
2) 调用SqlSession的方法(select/insert/update)需要指定Statement的id,存在硬编码,不利于代码维护.

Mapper映射开发

mapper映射开发方法只需编写DAO接口,MyBatis根据接口定义与mapper文件中的SQL语句动态创建接口实现.

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><!--?xml version="1.0" encoding="UTF-8" ?-->
<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></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

注意: 此时namespace必须与UserDAO接口的全限定名相同.

UserDAO接口与前面相同, 但不再使用UserDAOImpl Client

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java">/**
* @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();
}
}</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

mapper映射开发方法需要遵循以下规范:

mapper文件中的namespace与DAO接口的全限定名相同; mapper文件中的Statement的id与DAO接口方法名相同; mapper文件中的Statement的parameterType/resultType与DAO方法的入参/回参类型相同.

Mapper映射

mapper映射文件(如UserDAO.xml)主要作用是定义SQL语句(每个SQL是一个Statement),是MyBatis的核心.

MyBatis官方推荐使用mapper映射的方法来开发DAO,因此我们以后就不再过多介绍原始DAO的开发.

输入映射

多个形参

传递简单类型前面示例已经使用过,在此就不再赘述.当需要传递多个形参时,不再需要设置parameterType参数:

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><update id="updateUserById">
UPDATE user SET name = #{1}, password = #{2} WHERE id = #{0};
</update></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso">void updateUserById(Integer id, String name, String password) throws Exception;</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

传入PO

MyBatis使用OGNL表达式解析对象属性值:

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><select id="selectUserByNamePassword" parametertype="com.fq.domain.User" resulttype="com.fq.domain.User">
SELECT *
FROM user
WHERE name = #{name} AND password = #{password};
</select></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><code class="hljs java">User selectUserByNamePassword(User user) throws Exception;</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><code class="hljs java"><code class="hljs vbnet"><select id="selectUserByMap" parametertype="java.util.Map" resulttype="com.fq.domain.User">
SELECT *
FROM user
WHERE name = #{name} AND password = #{password};
</select></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

#{}花括号内对应Map的key.

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><code class="hljs java"><code class="hljs vbnet"><code class="hljs vhdl">User selectUserByMap(Map<string, object=""> map) throws Exception;</string,></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

输出映射

输出简单类型

mapper

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><code class="hljs java"><code class="hljs vbnet"><code class="hljs vhdl"><code class="hljs vbnet"><select id="selectUserCount" parametertype="java.lang.String" resulttype="java.lang.Integer">
SELECT count(*)
FROM user
WHERE name LIKE '%${value}%';
</select></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

UserDAO

<code class="hljs xml"><code class="hljs xml"><code class="hljs xml"><code class="hljs java"><code class="hljs java"><code class="hljs applescript"><code class="hljs java"><code class="hljs xml"><code class="hljs cs"><code class="hljs haml"><code class="hljs java"><code class="hljs livecodeserver"><code class="hljs java"><code class="hljs xml"><code class="hljs xml"><code class="hljs vbnet"><code class="hljs java"><code class="hljs java"><code class="hljs cs"><code class="hljs xml"><code class="hljs java"><code class="hljs haml"><code class="hljs lasso"><code class="hljs vbnet"><code class="hljs java"><code class="hljs vbnet"><code class="hljs vhdl"><code class="hljs vbnet"><code class="hljs mathematica">Integer selectUserCount(String name) throws Exception;</code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code></code>

返回简单类型必须保证查询结果只有一行记录,最终将第一个字段的值转换为输出类型.

输出PO对象/列表

前面已经演示过输出两种类型(selectUserById/selectUserByName虽然当时使用的是原始DAO开发方法, 但mapper定义形式大同小异),因此在这儿只做简单总结:

输出单个PO对象和输出PO列表在mapper中定义的resultType是一样的; 输出单个PO对象要保证SQL查询结果为单条数据,其内部使用selectOne方法调用; 输出PO列表表示查询结果可能为多条,其内部使用selectList方法调用,接口返回值可用List/Set承载.

输出Map

输出PO对象完全可以改用Map输出,字段名作key,字段值作value.

mapper

<code class="hljs vbnet"><select id="selectUserLikeName" resulttype="java.util.Map">
SELECT *
FROM user
WHERE name LIKE '%${value}%';
</select></code>

UserDAO

<code class="hljs vbnet"><code class="hljs mathematica">List<map<string, object="">> selectUserLikeName(String name) throws Exception;</map<string,></code></code>

resultMap

resultType可将查询结果映射为PO,但前提是PO属性名与SQL字段名必须一致,如不一致,则可通过resultMap作对应映射:

mapper

<code class="hljs vbnet"><code class="hljs mathematica"><code class="hljs applescript"><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">
</result></result></id></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></code></code></code>

UserDAO接口同前.

(0)

相关推荐

  • oracle+mybatis 使用动态Sql当插入字段不确定的情况下实现批量insert

    最近做项目遇到一个挺纠结的问题,由于业务的关系,DB的数据表无法确定,在使用过程中字段可能会增加,这样在insert时给我造成了很大的困扰. 先来看一下最终我是怎么实现的: <insert id="batchInsertLine" parameterType="HashMap"> <![CDATA[ INSERT INTO tg_fcst_lines(${lineColumn}) select result.*,sq_fcst_lines.next

  • MyBatis Mapper代理使用方法详解

    MyBatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 下文重点给大家介绍mapper代理使用方法. 一.开发人员需要完成的任务: mapper.xml映射文件和mapper.java 二.开发规范

  • MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法

    最近在项目中有这么一段代码:下载服务器基础业务数据进行本地批量插入操作,因项目中使用mybatis进行持久化操作,故直接考虑使用mybatis的批量插入功能. 1.以下是Mapper接口的部分代码 public interface PrintMapper { @InsertProvider(type = PrintMapperProvider.class,method = "insertAllLotWithVehicleCode4H2") void insertAllLotWithVe

  • Mybatis增删改查mapper文件写法详解

      1. 插入 <mapper namespace="需要实现接口的全类名"> <insert id="需要实现的接口里的方法名" parameterType="方法参数类型,如果是对象要写全类名"> INSERT sql命令(命令里通过#{}获取对象属性) <!--注意属性名区分大小写 --> </insert> <mapper> EG: <mapper namespace=&q

  • Java的MyBatis框架中Mapper映射配置的使用及原理解析

    Mapper的内置方法 model层就是实体类,对应数据库的表.controller层是Servlet,主要是负责业务模块流程的控制,调用service接口的方法,在struts2就是Action.Service层主要做逻辑判断,Dao层是数据访问层,与数据库进行对接.至于Mapper是mybtis框架的映射用到,mapper映射文件在dao层用. 下面是介绍一下Mapper的内置方法: 1.countByExample ===>根据条件查询数量 int countByExample(UserE

  • Mybatis实现Mapper动态代理方式详解

    一.实现原理 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法. Mapper接口开发需要遵循以下规范: 1.Mapper.xml文件中的namespace与mapper接口的类路径相同. 2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 3.Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的para

  • mybatis的动态sql详解(精)

    MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力.如果你有使用 JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号.动态 SQL 可以彻底处理这种痛苦. 通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中. 动态SQL元素和使用 JSTL或其他相似的基于XML的文本处理器相似.在MyBatis之前的版本中,有很多

  • 详解MyBatis的getMapper()接口、resultMap标签、Alias别名、 尽量提取sql列、动态操作

    一.getMapper()接口 解析:getMapper()接口 IDept.class定义一个接口, 挂载一个没有实现的方法,特殊之处,借楼任何方法,必须和小配置中id属性是一致的 通过代理:生成接口的实现类名称,在MyBatis底层维护名称$$Dept_abc,selectDeptByNo() 相当于是一个强类型 Eg 第一步:在cn.happy.dao中定义一个接口 package cn.happy.dao; import java.util.List; import cn.happy.e

  • Mybatis中SqlMapper配置的扩展与应用详细介绍(1)

    奋斗了好几个晚上调试程序,写了好几篇博客,终于建立起了Mybatis配置的扩展机制.虽然扩展机制是重要的,然而如果没有真正实用的扩展功能,那也至少是不那么鼓舞人心的,这篇博客就来举几个扩展的例子. 这次研读源码的起因是Oracle和MySQL数据库的兼容性,比如在Oracle中使用双竖线作为连接符,而MySQL中使用CONCAT函数:比如Oracle中可以使用DECODE函数,而MySQL中只能使用标准的CASE WHEN:又比如Oracle中可以执行DELETE FORM TABLE WHER

  • 使用Mybatis Generator结合Ant脚本快速自动生成Model、Mapper等文件的方法

    MyBatis简介: MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 相关阅读:MyBatis入门学习教程(一)-MyBatis快速入门 使用过Mybatis的同学都知道,针对每一个项目中使用到的数据库表都需要建

随机推荐