MyBatis简介
- MyBatis 本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了googlecode,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
- MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
- 对jdbc的封装框架有哪些:Hibernate,dbutils,jdbcTemplate[spring],mybatis
- 原理:Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
JDBC代码存在的问题
数据库连接频繁开启和关闭,会严重影响数据库的性能。
代码中存在硬编码,分别是数据库部分的硬编码和SQL执行部分的硬编码。
package com.wuzy.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.wuzy.bean.User;
public class Test {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://10.17.152.149:3306/picture";
// Database credentials
static final String USER = "picture";
static final String PASS = "122122";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
String sql;
sql = "SELECT id, username, sex FROM user";
ResultSet rs = stmt.executeQuery(sql);
List<User> list = new ArrayList<User>();
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String sex = rs.getString("sex");
User user = new User();
user.setId(id);
user.setUsername(username);
user.setSex(sex);
list.add(user);
}
System.out.println(list);
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stmt != null)
stmt.close();
} catch (SQLException se2) {
}
try {
if (conn != null)
conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
}
}
MyBatis的框架核心
- mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。
- mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
- 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
- SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
- Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型。
Mybatis开发
- 导包
- 添加log4j.properties
Mybatis使用的日志包是log4j的,所以需要添加log4j.properties。
在classpath下创建log4j.properties如下:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志级别在开发阶段设置成DEBUG,在生产阶段设置成INFO或者ERROR。
3. 编写配置文件
主配置文件(SqlMapConfig.xml)
在classpath(src)下,创建SqlMapConfig.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties" />
<!--配置别名 -->
<typeAliases>
<!--<typeAlias type="com.wuzy.model.User" alias="user"></typeAlias> -->
<!--指定包名,别名就是类名,第一个小写 User 别名就是user -->
<package name="com.wuzy.bean"></package>
<package name="com.wuzy.vo"></package>
</typeAliases>
<!-- 配置mybatis的环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用dbcp连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${driverClass}" />
<property name="url" value="${url}" />
<property name="username" value="${name}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!--告诉mybatis加载映射文件 -->
<mappers>
<mapper resource="com/wuzy/sqlmap/user.xml"></mapper>
<!--第一种:写映射文件的名字 -->
<!-- <mapper resource="com/wuzy/mapper/UserMapper.xml"></mapper> -->
<!--第二种:写类名,一定要有个映射文件与之对应 如果没有,那么在UserMapper要声明注解 -->
<!-- <mapper class="com.wuzy.mapper.UserMapper"></mapper> -->
<!--第三种:可以写包名 xml文件名需要和接口名一样 -->
<!-- <package name="com.wuzy.mapper"></package> -->
</mappers>
</configuration>
映射文件
<?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="user">
<!--根据id查询 -->
<!-- [id]:statement的id,要求在命名空间内唯一 [parameterType]:入参的java类型 [resultType]:查询出的单条结果集对应的java类型
[#{}]: 表示一个占位符? [#{id}]:表示该占位符待接收参数的名称为id。 注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义 -->
<select id="findUserById" parameterType="int"
resultType="com.wuzy.bean.User">
SELECT * FROM user WHERE id = #{a}
</select>
<!-- [${}]:表示拼接SQL字符串 [${value}]:表示要拼接的是简单类型参数。 注意: 简单类型:int,byte,... string
1、如果参数为简单类型时,${}里面的参数名称必须为value 2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order
by ${colname} -->
<select id="findUserByName" parameterType="String"
resultType="com.wuzy.bean.User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select>
<!--插入数据 这里的占位是写模型的属性 -->
<insert id="insertUser" parameterType="com.wuzy.bean.User">
INSERT INTO user (username,sex,birthday,address)
VALUE (#{username},#{sex},#{birthday},#{address});
</insert>
<!--删除 -->
<delete id="deleteUser" parameterType="int">
DELETE FROM user where id = #{id};
</delete>
<!--更新 -->
<update id="updateUser" parameterType="com.wuzy.bean.User">
UPDATE user SET address = #{address},sex = #{sex}
WHERE id = #{id}
</update>
<!--插入时自动返回主键id -->
<insert id="insertUser2" parameterType="com.wuzy.bean.User">
<!-- [selectKey标签]:通过select查询来生成主键 [keyProperty]:指定存放生成主键的属性 [resultType]:生成主键所对应的Java类型
[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句 [last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username,sex,birthday,address)
VALUE (#{username},#{sex},#{birthday},#{address});
</insert>
</mapper>
测试代码
package com.wuzy.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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.Test;
import com.wuzy.bean.User;
public class Test1 {
@Test
public void test1() throws IOException {
// a)读取配置文件;
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// b)通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
// c)通过SqlSessionFactory创建SqlSession。
SqlSession session = sessionFactory.openSession();
// d)调用SqlSession的操作数据库方法。
// 查询一条结果
User user = session.selectOne("findUserById", 10);
System.out.println(user);
// 查询多条结果
List<User> users = session.selectList("findUserByName", "张");
System.out.println(users);
// 关闭SqlSession。
session.commit();
}
}
- Mybatis增删改查
插入数据
<!--插入时自动返回主键id -->
<insert id="insertUser2" parameterType="com.wuzy.bean.User">
<!-- [selectKey标签]:通过select查询来生成主键 [keyProperty]:指定存放生成主键的属性 [resultType]:生成主键所对应的Java类型
[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句 [last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username,sex,birthday,address)
VALUE (#{username},#{sex},#{birthday},#{address});
</insert>
session.insert("insertUser", new User("小强", "男", new Date(), "广州"));
session.commit();
删除数据
<!--删除 -->
<delete id="deleteUser" parameterType="int">
DELETE FROM user where id = #{id};
</delete>
session.delete("deleteUser", 20);
session.commit();
修改数据
<!--更新 -->
<update id="updateUser" parameterType="com.wuzy.bean.User">
UPDATE user SET username = #{username},sex = #{sex}
WHERE id = #{id}
</update>
User user = new User();
user.setId(20);
user.setSex("女");
user.setUsername("刘亦菲");
session.update("updateUser", user);
session.commit();
查询数据
查询单条selectOne
<select id="findUserById" parameterType="int"
resultType="com.wuzy.bean.User">
SELECT * FROM user WHERE id = #{a}
</select>
session.selectOne("findUserById", 20);
session.commit();
查询多条selectList
<select id="findUserByName" parameterType="String"
resultType="com.wuzy.bean.User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select>
session.selectList("findUserByName", "张");
session.commit();
5.主键返回之MySQL自增主键
MySQL自增主键,是指在insert之前MySQL会自动生成一个自增的主键。
我们可以通过MySQL的函数获取到刚插入的自增主键:
LAST_INSERT_ID()
这个函数是在insert语句之后去调用。
<insert id="insertUser" parameterType="com.wuzy.bean.User">
<!--
[selectKey标签]:通过select查询来生成主键
[keyProperty]:指定存放生成主键的属性
[resultType]:生成主键所对应的Java类型
[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句
[last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
<!-- 如果主键的值是通过MySQL自增机制生成的,那么我们此处不需要再显示的给ID赋值 -->
INSERT INTO USER (username,sex,birthday,address)
VALUES(#{username},#{sex},#{birthday},#{address})
</insert>
6.主键返回之MySQL自增UUID
<insert id="insertUser" parameterType="com.gyf.domain.User">
<selectKey keyProperty="id" resultType="String" order="BEFORE">
SELECT UUID()
</selectKey>
INSERT INTO USER (username,sex,birthday,address)
VALUES(#{username},#{sex},#{birthday},#{address})
</insert>
7.总结
parameterType和resultType
parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。
resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。
#{}和${}
#{}:相当于预处理中的占位符?。
#{}里面的参数表示接收java输入参数的名称。
#{}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,#{}里面可以是value,也可以是其他。
#{}可以防止SQL注入。
${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。
${}会引起SQL注入,所以要谨慎使用。
${}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,${}里面只能是value。
selectOne和selectList
selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
selectList:可以查询0或N条记录
Mybatis的dao方式开发(一般不用)
dao层代码
package com.wuzy.dao;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.wuzy.bean.User;
public class UserDaoImpl implements UserDao {
private SqlSessionFactory ssf;
public UserDaoImpl() {
}
public UserDaoImpl(SqlSessionFactory ssf) {
this.ssf = ssf;
}
@Override
public void save(User user) {
// 获取session
SqlSession session = ssf.openSession();
// 插入数据
session.insert("insertUser", user);
session.commit();
session.close();
}
@Override
public User findUserById(int id) {
// 获取session
SqlSession session = ssf.openSession();
// 插入数据
User user = session.selectOne("findUserById", id);
session.close();
return user;
}
}
测试
package com.wuzy.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import com.wuzy.bean.User;
import com.wuzy.dao.UserDao;
import com.wuzy.dao.UserDaoImpl;
public class Test2 {
SqlSessionFactory sessionFactory;
@Before
public void before() throws IOException {
System.out.println("before.....获取session");
// a)读取配置文件;
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//b)通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
sessionFactory = new SqlSessionFactoryBuilder().build(is);
}
@Test
public void test1() throws IOException {
//调用dao
//1.创建dao
UserDao userDao = new UserDaoImpl(sessionFactory);
User user1 = userDao.findUserById(1);
System.out.println(user1);
User user2 = new User("旺财","女",new Date(),"香港");
userDao.save(user2);
}
}
Mybati的mapper代理方式开发
Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。
不过要实现mapper代理的开发方式,需要遵循一些开发规范。
- mapper开发规范
- mapper接口的全限定名要和mapper映射文件的namespace的值相同。
- mapper接口的方法名称要和mapper映射文件中的statement的id相同;
- mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
- mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;
- 通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:
模板代码已经去掉;
剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。
- mapper接口
package com.wuzy.mapper;
import java.util.List;
import java.util.Map;
import com.wuzy.bean.User;
import com.wuzy.vo.UserQueryVO;
public interface UserMapper {
/**
*
* @param user
* @return 受影响的行数
*/
public int save(User user);
public User findUserById(int id);
public List<User> findUserByUserQueryVo(UserQueryVO vo);
public List<User> findUserByMap(Map<String, Object> map);
}
- mapper.xml文件
<?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.wuzy.mapper.UserMapper">
<insert id="save" parameterType="user">
INSERT INTO user
(username,sex,birthday,address)
VALUE
(#{username},#{sex},#{birthday},#{address})
</insert>
<select id="findUserById" parameterType="int" resultType="user">
SELECT
* FROM user WHERE id = #{id}
</select>
<!--通过包装类查询用户 -->
<select id="findUserByUserQueryVo" parameterType="userQueryVO"
resultType="user">
SELECT u.* FROM user u WHERE u.id = #{user.id}
</select>
<!--通过Map查询数据 -->
<select id="findUserByMap" parameterType="hashmap"
resultType="user">
SELECT u.* FROM user u WHERE username LIKE '%${username}%'
AND sex = #{sex}
</select>
<select id="findUserByName" parameterType="String"
resultType="user">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select>
</mapper>
- 测试
package com.wuzy.test;
import java.io.IOException;
import java.io.InputStream;
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 com.wuzy.mapper.UserMapper;
public class Test3 {
SqlSession session;
@Before
public void before() throws IOException {
System.out.println("before.....获取session");
// a)读取配置文件;
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// b)通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
session = sessionFactory.openSession();
}
@After
public void after() {
session.close();
}
@Test
public void test1() throws IOException {
UserMapper userMapper = session.getMapper(UserMapper.class);
// 获取数据
System.out.println(userMapper.findUserById(1));
}
}
Mybatis主配置文件中的其他配置
别名配置
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
自定义别名
<!--配置别名 -->
<typeAliases>
<!--<typeAlias type="com.wuzy.bean.User" alias="user"></typeAlias> -->
<!--指定包名,别名就是类名,第一个小写 User 别名就是user -->
<package name="com.wuzy.bean"></package>
<package name="com.wuzy.vo"></package>
</typeAliases>
mappers
<mapper resource=’’/>
使用相对于类路径的资源
如:<mapper resource="sqlmap/User.xml" />
<mapper url=’’/> 【不用】
使用完全限定路径
如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
<mapper class=’’/>
使用mapper接口的全限定名
如:<mapper class="cn.wuzy.mapper.UserMapper"/>
也可使用注解开发,把xml文件删除
@Insert("INSERT INTO user (username,sex,birthday,address) VALUE (#{username},#{sex},#{birthday},#{address})")
public int save(User user);
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
<package name=’’/>(推荐)
注册指定包下的所有映射文件
如:<package name="cn.wuzy.mapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
Mybatis映射文件
- 输入映射ParameterType
指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型,POJO对象、HashMap。 - 传递简单类型
<select id="findUserById" parameterType="int" resultType="user">
SELECT
* FROM user WHERE id = #{id}
</select>
- 传递POJO对象
<insert id="save" parameterType="user">
INSERT INTO user
(username,sex,birthday,address)
VALUE
(#{username},#{sex},#{birthday},#{address})
</insert>
- 传递hashmap
<!--通过Map查询数据 -->
<select id="findUserByMap" parameterType="hashmap"
resultType="user">
SELECT u.* FROM user u WHERE username LIKE '%${username}%'
AND sex = #{sex}
</select>
- 传递POJO包装对象
<select id="findUserByUserQueryVo" parameterType="userQueryVO"
resultType="user">
SELECT u.* FROM user u WHERE u.id = #{user.id}
</select>
package com.wuzy.vo;
import com.wuzy.bean.Order;
import com.wuzy.bean.User;
public class UserQueryVO {
private User user;
private Order order;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对
象传递输入参数。
需求
综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。
vo:键值对对象,相对于kv
po:persist object 持久化对象
pojo:简单的java对象
entity:实体
- 输出映射 resultType/resultMap
- resultType
使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象;
如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象。- 输出简单类型
当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型。
案例: - 输出一个count(*)
<!-- 查询用户的个数 --> <select id="findUserCount" parameterType="userQueryVO" resultType="int"> SELECT COUNT(*) FROM user WHERE sex = #{user.sex} </select>
public int findUserCount(UserQueryVO vo);
@Test public void test1() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 通过模型的包装类来查询 UserQueryVO query = new UserQueryVO(); User user = new User(); user.setSex("2");// 男性 query.setUser(user); int count = userMapper.findUserCount(query); System.out.println("男性的用户人数:" + count); }
- 输出POJO单个对象
<select id="findUserById" parameterType="int" resultType="user"> SELECT * FROM user WHERE id = #{id} </select>
public User findUserById(int id);
@Test public void test() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.findUserById(20); System.out.println("男性的用户人数:" + user); }
- 输出POJO列表
<select id="findUserList" parameterType="userQueryVO" resultType="user"> SELECT * FROM user <where> <include refid="select_user_where" /> </where> </select> <sql id="select_user_where"> <if test="user != null"> <if test="user.sex != null and user.sex != ''"> sex = #{user.sex} </if> <if test="user.username != null and user.username != ''"> and username LIKE '%${user.username}%' </if> <if test="user.address != null and user.address != ''"> and address LIKE '%${user.address}%' </if> </if> </sql>
public List<User> findUserList(UserQueryVO vo);
@Test public void test() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 通过模型的包装类来查询 UserQueryVO query = new UserQueryVO(); User user = new User(); user.setSex("2");// 男性 query.setUser(user); List<User> list = userMapper.findUserList(query); System.out.println("男性的用户人数:" + list); }
- 总结
输出单个pojo对象和pojo列表时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。
同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。
- 输出简单类型
- resultMap
如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。
1、 定义resultMap
2、使用resultMap作为statement的输出映射类型<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> SELECT id id_, username username_, sex sex_, birthday birthday_, address address_ FROM user WHERE id = #{id} </select>
public User findUserByIdResultMap(int userId);
@Test public void test2() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.findUserByIdResultMap(1); System.out.println("用户数据:" + user); }
- resultType
5 动态SQL
-
if和where
- If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’; - Where标签:会去掉条件中的第一个and符号。
<select id="findUserList" parameterType="userQueryVO" resultType="user"> /*性别和名字*/ SELECT * FROM user <where> <if test="user != null"> <if test="user.sex != null and user.sex != ''"> sex = #{user.sex} </if> <if test="user.username != null and user.username != ''"> and username LIKE '%${user.username}%' </if> <if test="user.address != null and user.address != ''"> and address LIKE '%${user.address}%' </if> </if> </where> </select>
public List<User> findUserList(UserQueryVO vo);
@Test public void test3() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 查询条件 UserQueryVO query = new UserQueryVO(); User user = new User(); user.setSex("1");// 男性 user.setUsername("张"); query.setUser(user); List<User> users = userMapper.findUserList(query); System.out.println(users); }
- If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
-
SQL片断
<sql id="select_user_where"> <if test="user != null"> <if test="user.sex != null and user.sex != ''"> sex = #{user.sex} </if> <if test="user.username != null and user.username != ''"> and username LIKE '%${user.username}%' </if> <if test="user.address != null and user.address != ''"> and address LIKE '%${user.address}%' </if> </if> </sql> <select id="findUserList" parameterType="userQueryVO" resultType="user"> /*性别和名字*/ SELECT * FROM user <where> <include refid="select_user_where"/> </where> </select>
public List<User> findUserList(UserQueryVO vo);
@Test public void test3() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 查询条件 UserQueryVO query = new UserQueryVO(); User user = new User(); user.setSex("1");// 男性 user.setUsername("张"); query.setUser(user); List<User> users = userMapper.findUserList(query); System.out.println(users); }
-
foreach 遍历
<select id="findUserByIds" parameterType="userQueryVO" resultType="user"> <!--性别和名字 SELECT * FROM user WHERE id in (1,2,3) --> SELECT * FROM user <where> <if test="ids != null and ids.size > 0"> <!-- collection:集合,写集合属性 item:遍历接收变量 open:遍历开始 close:遍历结束 separator:拼接格式 for(Integer id : ids){ } --> <foreach collection="ids" item="id" open="id in(" close=")" separator=","> ${id} </foreach> </if> </where> </select> <!-- 5.参数是数组 如果参数是数组的话,parameterType可以写全名【java.util.List】,也可以写别名 遍历或者判断的时候,都用list变量 --> <select id="findUserByIds2" parameterType="list" resultType="user"> <!--性别和名字 SELECT * FROM user WHERE id in (1,2,3) --> SELECT * FROM user <where> <if test="list != null and list.size > 0"> <foreach collection="list" item="id" open="id in(" close=")" separator=","> ${id} </foreach> </if> </where> </select>
/* 查找多个id的用户数据 */ public List<User> findUserByIds(UserQueryVO vo); public List<User> findUserByIds2(List<Integer> ids);
@Test public void test4() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 查询条件 UserQueryVO query = new UserQueryVO(); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(10); ids.add(16); query.setIds(ids); List<User> users = userMapper.findUserByIds(query); System.out.println(users); } @Test public void test5() throws IOException { UserMapper userMapper = session.getMapper(UserMapper.class); // 查询条件 List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(10); ids.add(16); List<User> users = userMapper.findUserByIds2(ids); System.out.println(users); }
mybatis与hibernate的区别
- Mybatis技术特点
好处:
1. 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2. 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3. 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
缺点:
1. 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
a)Mysql:limit
b)Oracle:rownum
2.需要编写结果映射 - Hibernate技术特点
好处:
1. 标准的orm框架,程序员不需要编写SQL语句。
2. 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
a)以后,mysql数据迁移到oracle,只需要改方言配置
缺点:
1. 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
2.程序员不能自主的去进行SQL性能优化 - Mybatis应用场景
需求多变的互联网项目,例如电商项目。 - Hibernate应用场景
需求明确、业务固定的项目,例如OA项目、ERP项目等。
关联查询
表关系
- user和orders:
User 与orders:一个用户可以创建多个订单,一对多
Orders 与 user:多个订单只由一个用户创建,多对一 - orders和orderdetail:
Orders 与 orderdetail:一个订单可以包括多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多关系
orderdetail 与orders:多个订单明细包括在一个订单中, 多对一 - orderdetail和items:
Orderdetail 与 items:多个订单明细只对应一个商品信息,多对一
Items 与 orderdetail:一个商品可以包括在多个订单明细 ,一对多
一对一查询
-
复杂查询时,单表对应的po类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型。
需求:#查找某个定单id的信息,包括用户名字和地址 SELECT o.*,u.username,u.address FROM orders o,user u WHERE o.user_id = u.id AND o.id = 3
-
编写订单的扩展类
package com.wuzy.bean; public class OrdersExt extends Orders{ private String username; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "OrdersExt{" + "username='" + username + '\'' + ", address='" + address + '\'' + '}' + super.toString(); } }
-
声明订单接口
public OrdersExt findOrderById(int id);
-
编写xml文件
<select id="findOrderById" parameterType="int" resultType="ordersExt"> SELECT o.*,u.username,u.address FROM orders o,user u WHERE o.user_id = u.id AND o.id = #{id} </select>
-
测试代码
/** * 一对一 : 写个定单的扩展类 * * @throws IOException */ @Test public void test6() throws IOException { OrderMapper mapper = session.getMapper(OrderMapper.class); OrdersExt ordersExt = mapper.findOrderById(3); System.out.println(ordersExt); }
-
resultMap实现
- 订单中包含user对象
package com.wuzy.bean; import java.util.Date; import java.util.List; public class Orders { private Integer id; private Integer user_id; private String note;//备注 private String number; private Date createtime;//写意的创建时间 private User user;//定单所属的用户 /* 一对多数据封装*/ private List<OrderDetail> orderDetails; public List<OrderDetail> getOrderDetails() { return orderDetails; } public void setOrderDetails(List<OrderDetail> orderDetails) { this.orderDetails = orderDetails; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Orders{" + "id=" + id + ", user_id=" + user_id + ", note='" + note + '\'' + ", number='" + number + '\'' + ", createtime=" + createtime + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUser_id() { return user_id; } public void setUser_id(Integer user_id) { this.user_id = user_id; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } }
- 定义接口
public Orders findOrderById2(int id);
- 编写xml
<!-- =============== 一对一 ================= --> <!--如果模型里有模型,使用resultMap --> <resultMap id="orderRslMap" type="orders"> <!-- 往orders的模型匹配数据 --> <id column="id" property="id"></id> <id column="note" property="note"></id> <id column="number" property="number"></id> <id column="createtime" property="createtime"></id> <!-- 往orders的user匹配数据 模型里有模型,使用association来配置 --> <association property="user" javaType="user"> <id column="user_id" property="id"></id> <id column="username" property="username"></id> <id column="address" property="address"></id> </association> </resultMap> <select id="findOrderById2" parameterType="int" resultMap="orderRslMap"> SELECT o.*,u.username,u.address FROM orders o,user u WHERE o.user_id = u.id AND o.id = #{id} </select>
- 测试代码
/** * 一对一 : 模型里有模型 * * @throws IOException */ @Test public void test7() throws IOException { OrderMapper mapper = session.getMapper(OrderMapper.class); Orders order = mapper.findOrderById2(3); System.out.println(order); System.out.println(order.getUser()); }
- 订单中包含user对象
一对多查询
需求:
根据定单ID查找定单信息、用户信息和定单明细信息
Select
orders.id,
orders.user_id,
orders.number,
orders.createtime,
orders.note,
user.username,
user.address,
orderdetail.id detail_id,
orderdetail.items_id,
orderdetail.items_num
from
orders,user,orderdetail
where
orders.user_id = user.id
and orders.id = orderdetail.orders_id
and orders.id = #{?};
SELECT
o.*,
u.username,
u.address,
od.id detail_id,
od.items_id,
od.items_num
FROM
orders o,
user u,
orderdetail od
WHERE
o.user_id = u.id
AND o.id = od.orders_id
AND o.id = 3
- 在Orders中添加定单明细
package com.wuzy.bean;
import java.util.Date;
import java.util.List;
public class Orders {
private Integer id;
private Integer user_id;
private String note;//备注
private String number;
private Date createtime;//写意的创建时间
private User user;//定单所属的用户
/* 一对多数据封装*/
private List<OrderDetail> orderDetails;
public List<OrderDetail> getOrderDetails() {
return orderDetails;
}
public void setOrderDetails(List<OrderDetail> orderDetails) {
this.orderDetails = orderDetails;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Orders{" +
"id=" + id +
", user_id=" + user_id +
", note='" + note + '\'' +
", number='" + number + '\'' +
", createtime=" + createtime +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
- 编写mapper接口
public Orders findOrderById3(int id);
- 编写xml
<!-- ================一对多================== -->
<resultMap id="orderRslMap3" type="orders">
<!-- 往orders的模型匹配数据 -->
<id column="id" property="id"></id>
<id column="note" property="note"></id>
<id column="number" property="number"></id>
<id column="createtime" property="createtime"></id>
<!-- 往orders的user匹配数据 模型里有模型,使用association来配置 -->
<association property="user" javaType="user">
<id column="user_id" property="id"></id>
<id column="username" property="username"></id>
<id column="address" property="address"></id>
</association>
<!-- 一对多匹配: 往orders的orderdetails 匹配数据 注意:集合里类型使用ofType,而不javaType -->
<collection property="orderDetails" ofType="orderDetail">
<id column="detail_id" property="id"></id>
<id column="items_id" property="itemsId"></id>
<id column="items_num" property="itemsNum"></id>
</collection>
</resultMap>
<select id="findOrderById3" parameterType="int"
resultMap="orderRslMap3">
SELECT
o.*,
u.username,
u.address,
od.id detail_id,
od.items_id,
od.items_num
FROM
orders o,
user u,
orderdetail od
WHERE
o.user_id = u.id
AND o.id = od.orders_id
AND o.id = #{id}
</select>
- 测试代码
/**
* 一对多 : 模型里有集合
*
* @throws IOException
*/
@Test
public void test8() throws IOException {
OrderMapper mapper = session.getMapper(OrderMapper.class);
Orders order = mapper.findOrderById3(3);
System.out.println(order);
System.out.println(order.getUser());
System.out.println(order.getOrderDetails());
}
- 总结
mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。
使用resultType实现:
需要对结果集进行二次处理。将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。
多对多查询
需求:
查询用户信息及用户购买的商品信息,要求将关联信息映射到主pojo的pojo属性中
Select
user.id,
user.username,
user.address,
orders.id orders_id,
orders.user_id,
orders.number,
orders.createtime,
orders.note,
orderdetail.id detail_id,
orderdetail.items_id,
orderdetail.items_num,
items.name items_name,
items.detail items_detail
FROM
USER,orders,orderdetail,items
WHERE user.`id` = orders.`user_id`
AND orders.`id` = orderdetail.`orders_id`
AND orderdetail.`items_id` = items.`id`
SELECT
u.id,
u.username,
u.address,
o.id order_id,
o.number,
o.createtime,
o.note,
od.id detail_id,
od.items_id,
od.items_num,
it.name,
it.price,
it.detail
FROM
user u,
orders o,
orderdetail od,
items it
WHERE
o.user_id = u.id
AND o.id = od.orders_id
AND od.items_id = it.id;
- 将用户信息映射到user中。
- 在user类中添加订单列表属性List orderslist,将用户创建的订单映射到orderslist
- 在Orders中添加订单明细列表属性List detailList,将订单的明细映射到detailList
- 在Orderdetail中添加Items属性,将订单明细所对应的商品映射到Items
开发流程
- 修改user类
package com.wuzy.bean;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1705381513476930984L;
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
private List<Orders> orderList;// 一个用户有多张定单
public List<Orders> getOrderList() {
return orderList;
}
public void setOrderList(List<Orders> orderList) {
this.orderList = orderList;
}
public User() {
}
public User(String username, String sex, Date birthday, String address) {
this.username = username;
this.sex = sex;
this.birthday = birthday;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
+ address + "]";
}
}
- 编写接口
public List<User> findUserAndOrderInfo();
- 编写xml
<!-- ==============查询用户信息及用户购买的商品信息============-->
<resultMap id="userRslMap" type="user">
<!-- 1.匹配user属性 -->
<id column="id" property="id"></id>
<result column="username" property="username"/>
<result column="password" property="password"/>
<!--2.匹配user的orderList-->
<collection property="orderList" ofType="orders">
<id column="order_id" property="id"></id>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 3.匹配Orders里有orderDetails-->
<collection property="orderDetails" ofType="orderDetail">
<id column="detail_id" property="id"></id>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<!-- 4.配置定单详情的商品信息-->
<association property="items" javaType="items">
<id column="items_id" property="id"/>
<result column="name" property="name"/>
<result column="price" property="price"/>
<result column="detail" property="detail"/>
</association>
</collection>
</collection>
</resultMap>
<select id="findUserAndOrderInfo" resultMap="userRslMap">
SELECT
u.id,
u.username,
u.address,
o.id order_id,
o.number,
o.createtime,
o.note,
od.id detail_id,
od.items_id,
od.items_num,
it.name,
it.price,
it.detail
FROM
user u,
orders o,
orderdetail od,
items it
WHERE
o.user_id = u.id
AND o.id = od.orders_id
AND od.items_id = it.id
</select>
- 测试代码
/**
- 多对多
-
- @throws IOException
*/
@Test
public void test9() throws IOException {
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.findUserAndOrderInfo();
for (User user : users) {
System.out.println("用户信息:" + user);
for (Orders order : user.getOrderList()) {
System.out.println("定单信息:" + order);
System.out.println("订单详情:");
for (OrderDetail od : order.getOrderDetails()) {
System.out.println(od + ":" + od.getItems());
}
System.out.println("------------------------------");
}
}
}
延时加载
延迟加载又叫懒加载,也叫按需加载。也就是说先加载主信息,在需要的时候,再去加载从信息。
在mybatis中,resultMap标签的association标签和collection标签具有延迟加载的功能。
- mapper接口
/**
* 懒加载定单的用户数据
*
* @return
*/
public List<Orders> findOrderAndUserByLazyloading();
- 编写xml文件
<!-- ============= 懒加载 ================== -->
<resultMap id="orderLazyloadingRslMap" type="orders">
<id column="id" property="id" />
<result column="note" property="note" />
<result column="number" property="number" />
<result column="createtime" property="createtime" />
<!--配置查询 -->
<association property="user"
select="com.wuzy.mapper.UserMapper.findUserById" column="user_id" />
</resultMap>
<select id="findOrderAndUserByLazyloading"
resultMap="orderLazyloadingRslMap">
SELECT * FROM orders
</select>
- 开启懒加载
<!--配置允许懒加载 -->
<settings>
<setting name="lazyLoadingEnabled" value="true" />
</settings>
- 测试
@Test
public void test10() throws IOException {
OrderMapper mapper = session.getMapper(OrderMapper.class);
List<Orders> list = mapper.findOrderAndUserByLazyloading();
for (Orders order : list) {
System.out.println("订单信息:");
System.out.println(order);
System.out.println("订单所属的客户:");
System.out.println(order.getUser());
}
}
mybatis整合spring
- 向dao注入sessionFactory
- spring配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 1.配置数据库,c3p0数据库连接池--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.name}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 2.配置会话工厂--> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:SqlMapConfig.xml"/> </bean> <!-- ===============配置dao的几种方式=================--> <!-- 第一种 --> <!--3.传统配置dao,【现在不用】--> <bean id="userDao" class="com.wuzy.dao.UserDaoImpl"> <!-- <property name="sqlSessionFactory" ref="sessionFactory"/> --> <constructor-arg name="ssf" ref="sessionFactory"></constructor-arg> </bean> </beans>
- mybatis主配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="db.properties" /> <!--配置允许懒加载 --> <settings> <setting name="lazyLoadingEnabled" value="true" /> </settings> <!--配置别名 --> <typeAliases> <!--<typeAlias type="com.gyf.model.User" alias="user"></typeAlias> --> <!--指定包名,别名就是类名,第一个小写 User 别名就是user --> <package name="com.wuzy.bean"></package> <package name="com.wuzy.vo"></package> </typeAliases> <!-- 配置mybatis的环境信息 --> <!-- <environments default="development"> <environment id="development"> 配置JDBC事务控制,由mybatis进行管理 <transactionManager type="JDBC"></transactionManager> 配置数据源,采用dbcp连接池 <dataSource type="POOLED"> <property name="driver" value="${driverClass}" /> <property name="url" value="${url}" /> <property name="username" value="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> --> <!--告诉mybatis加载映射文件 --> <mappers> <!--<mapper resource="com/gyf/sqlmap/User.xml"></mapper> --> <!--第一种:写映射文件的名字 --> <!--<mapper resource="com/gyf/mapper/UserMapper.xml"></mapper> --> <!--第二种:写类名,一定要有个映射文件与之对应 如果没有,那么在UserMapper要声明注解 --> <!--<mapper class="com.gyf.mapper.UserMapper"></mapper> --> <!--第三种:可以写包名 --> <package name="com.wuzy.mapper"></package> </mappers> </configuration>
- dao注入sessionFactory
package com.wuzy.dao; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import com.wuzy.bean.User; public class UserDaoImpl implements UserDao { private SqlSessionFactory ssf; public UserDaoImpl() { } public UserDaoImpl(SqlSessionFactory ssf) { this.ssf = ssf; } @Override public void save(User user) { // 获取session SqlSession session = ssf.openSession(); // 插入数据 session.insert("insertUser", user); session.commit(); session.close(); } @Override public User findUserById(int id) { // 获取session SqlSession session = ssf.openSession(); // 插入数据 User user = session.selectOne("findUserById", id); session.close(); return user; } }
- 测试
@Test public void test1() { // 1.加载spring的配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2.获取dao的bean UserDao userDao = (UserDao) context.getBean("userDao"); // 3.调用dao方法 User user = userDao.findUserById(1); System.out.println(user); }
- spring配置文件
- mapper代理
- mapper配置
<select id="findUserById" parameterType="int" resultType="user"> SELECT * FROM user WHERE id = #{id} </select>
- mapper主配置文件
<mappers> <package name="com.wuzy.mapper"></package> </mappers>
- spring配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 1.配置数据库,c3p0数据库连接池--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.name}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 2.配置会话工厂--> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:SqlMapConfig.xml"/> </bean> <!-- ===============配置dao的几种方式=================--> <!-- 第一种 --> <!--3.传统配置dao,【现在不用】--> <!-- <bean id="userDao" class="com.wuzy.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sessionFactory"/> <constructor-arg name="ssf" ref="sessionFactory"></constructor-arg> </bean> --> <!-- 第二种 --> <!--4.由spring创建一个userMapper对象,使用工厂来创建--> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sessionFactory"/> <property name="mapperInterface" value="com.wuzy.mapper.UserMapper"/> </bean> <!-- 第三种 --> <!-- 批量创建mapper的bean对象 内部会扫描指定包下的mapper,创建代理对象,名字就是类名,头字母改小写 --> <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wuzy.mapper.UserMapper"/> <property name="sqlSessionFactoryBeanName" value="sessionFactory"/> </bean> --> </beans>
- 接口
public interface UserDao { public User findUserById(int id); }
- 测试
@Test public void test2() { // 1.加载spring的配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2.获取userMapper UserMapper userMapper = (UserMapper) context.getBean("userMapper"); // 3.调用dao方法 User user = userMapper.findUserById(1); System.out.println(user); }
- mapper配置
- spring扫描
测试代码<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 1.配置数据库,c3p0数据库连接池--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.name}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 2.配置会话工厂--> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 别名 --> <property name="typeAliasesPackage" value="com.wuzy"></property> <!-- <property name="configLocation" value="classpath:SqlMapConfig.xml"/> --> <property name="mapperLocations" value="classpath*:com/wuzy/mapper/*Mapper.xml"></property> </bean> <!-- ===============配置dao的几种方式=================--> <!-- 第一种 --> <!--3.传统配置dao,【现在不用】--> <!-- <bean id="userDao" class="com.wuzy.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sessionFactory"/> <constructor-arg name="ssf" ref="sessionFactory"></constructor-arg> </bean> --> <!-- 第二种 --> <!--4.由spring创建一个userMapper对象,使用工厂来创建--> <!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sessionFactory"/> <property name="mapperInterface" value="com.wuzy.mapper.UserMapper"/> </bean> --> <!-- 第三种 --> <!-- 批量创建mapper的bean对象 内部会扫描指定包下的mapper,创建代理对象,名字就是类名,头字母改小写 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wuzy.mapper"/> <property name="sqlSessionFactoryBeanName" value="sessionFactory"/> </bean> </beans>
@Test public void test2() { // 1.加载spring的配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2.获取userMapper UserMapper userMapper = (UserMapper) context.getBean("userMapper"); // 3.调用dao方法 User user = userMapper.findUserById(1); System.out.println(user); }