基础:Dao开发
跳到导航
跳到搜索
关于
使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法。
原始Dao开发
User.java
public class User {
//属性名和数据库表的字段对应
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String 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 + "]";
}
}
User.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="test">
<!-- 在 映射文件中配置很多sql语句 -->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE id=#{value}
</select>
<!-- 根据用户名称模糊查询用户信息,可能返回多条 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE username LIKE '%${value}%'
</select>
<!-- 添加用户 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 删除 用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!-- 根据id更新用户 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
</mapper>
- 需要在SqlMapConfig.xml中添加映射文件。
UserDao.java
public interface UserDao {
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;
//添加用户信息
public void insertUser(User user) throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
}
UserDaoImpl.java
public class UserDaoImpl implements UserDao {
// 需要向dao实现类中注入SqlSessionFactory
// 这里通过构造方法注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User user = sqlSession.selectOne("test.findUserById", id);
} finally{
session.close();
}
return user;
}
@Override
public List<User> findUserByName(String name) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
List<User> list = sqlSession.selectList("test.findUserByName", name);
} finally{
session.close();
}
return list;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.insert("test.insertUser", user);
} finally{
session.close();
}
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.delete("test.deleteUser", id);
sqlSession.commit();
} finally{
session.close();
}
}
}
- 实现UserDao接口方法;
- 注入sqlSessionFactory(构造方法或其他方法注入)到私有属性sqlSessionFactory;
- 方法体中,通过sqlSession(线程不安全,方法体内)实现数据交互;
- (“SqlSession sqlSession = sqlSessionFactory.openSession();”会读取相应配置及映射文件内容;)
- 资源的关闭与释放(最好添加try-catch块???);
测试:UserDaoImplTest.java
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
// 创建UserDao的对象
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 调用UserDao的方法
User user = userDao.findUserById(1);
System.out.println(user);
}
}
- 业务代码中应该先获取配置文件流,并由sqlSessionFactoryBuilder(一次性,方法局部变量)生成sqlSessionFactory对象(共用,应用运行期内);
- 用sqlSessionFactory做为参数,创建接口实现类的对象;
- UserDao userDao = new UserDaoImpl(sqlSessionFactory); 多态,向上转型
问题
原始Dao开发中存在以下问题:
- 代码重复:Dao实现类的方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
SqlSession sqlSession = sqlSessionFactory.openSession(); try { sqlSession.insert("insertUser", user); sqlSession.commit(); } finally{ session.close(); }
- 硬编码:调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。
sqlSession.insert("insertUser", user);
Mapper动态代理
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
- (省略了接口实现类,通过反射来实现)
使用规范
Mapper接口开发需要遵循以下规范:
- Mapper.xml文件中的namespace与mapper接口的类路径相同。
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
User.java
(同上,略)
- 路径:“cn.itcast.mybatis.po.User”;
UserMapper.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="cn.itcast.mybatis.mapper.UserMapper">
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
select * from user where id = #{id}
</select>
<!-- 自定义条件查询用户列表 -->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
<!-- 添加用户 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
- (需要在SqlMapConfig.xml中添加映射文件)
- namespace 为 UserMapper.java路径(“cn.itcast.mybatis.mapper.UserMapper”);
- UserMapper.xml 与 UserMapper.java 同名不同后缀,且位于同一路径下;
UserMapper.java
Public interface UserMapper {
//根据用户id查询用户信息
public User findUserById(int id) throws Exception;
//查询用户列表
public List<User> findUserByUsername(String username) throws Exception;
//添加用户信息
public void insertUser(User user)throws Exception;
}
- 路径:“cn.itcast.mybatis.po.User”;
接口定义有如下特点:
- UserMapper.java 与 UserMapper.xml 同名不同后缀,且位于同一路径下;
- ..方法名 与 ...statement的id相同
- ..方法的输入参数类型 与 ...statement的parameterType的类型相同
- ..方法的输出参数类型 与 ...statement的resultType的类型相同
测试 UserMapperTest.java
Public class UserMapperTest extends TestCase {
private SqlSessionFactory sqlSessionFactory;
protected void setUp() throws Exception {
//mybatis配置文件
String resource = "sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//使用SqlSessionFactoryBuilder创建sessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
Public void testFindUserById() throws Exception {
//获取session
SqlSession session = sqlSessionFactory.openSession();
//获取mapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用代理对象方法
User user = userMapper.findUserById(1);
System.out.println(user);
//关闭session
session.close();
}
@Test
public void testFindUserByUsername() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.findUserByUsername("张");
System.out.println(list.size());
}
Public void testInsertUser() throws Exception {
//获取session
SqlSession session = sqlSessionFactory.openSession();
//获取mapper接口的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
//要添加的数据
User user = new User();
user.setUsername("张三");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("北京市");
//通过mapper接口添加用户
userMapper.insertUser(user);
//提交
session.commit();
//关闭session
session.close();
}
}
- 利用反射来获取接口实现类:
UserMapper userMapper = session.getMapper(UserMapper.class);