您的位置:首页 > 其它

Mybatis原始的dao开发

2016-09-04 14:38 302 查看
首先给出直接通过传统的JDBC访问数据库实例

import java.sql.*;

/**
* Created by hsc on 16/8/27.
*/
public class JdbcTest {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static String userName = "test"; //连接数据库用户名
private static String password = "test123";//连接数据库的密码
private static String connectionUrl = "jdbc:mysql://IP地址:端口/数据库名";

public static void queryTest(String sql, Object[] params){

//数据库的连接
Connection connection = null;
ResultSet resultSet = null;
//预编译的Statement 向数据库发送sql语句,数据库那边进行编译,数据那边将编译结果存放在缓存
PreparedStatement preparedStatement = null;

try {

Class.forName(JdbcTest.DRIVER);
connection = DriverManager.getConnection(connectionUrl, userName, password);
preparedStatement = connection.prepareStatement(sql);
// 参数赋值,向占位符中填充数据
if (params != null) {
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
}

resultSet = preparedStatement.executeQuery();

//遍历查询结果集
while (resultSet.next()) {
System.out.println(resultSet.getString(1));
}

} catch (Exception ex) {
System.out.println(ex.getMessage());
//释放资源
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {

System.out.println(e.getMessage());
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

public static void main(String args[]) {
//问号表示占位符
String querySql = "select * from st_didinfo limit ?";
Object[] objects = new Object[1];
objects[0] = 5;
queryTest(querySql, objects);

}
}
从上面的程序不难发现有以下问题

1.使用时候创建,不使用的时候立即释放,对数据库进行频繁的连接和开启,造成了数据库资源的浪费,影响数据库的性能

2.将sql语句硬编码()到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统的维护

设想:如果能将sql语句配置在文件中,即使sql变化了,也不需要对java代码进行重新编译。

3.向PreparedStatement设置参数,对占位符把控设置和设置参数值,硬编码在java中利于系统的维护

4.从resultSet中遍历数据结果时候,存在硬编码,将表字段进行硬编码,不利于系统维护

Mybatis是持久层框架,是和数据库打交道的框架,

让程序员主要精力放在sql上,通过mybaits提供映射方式,自由灵活生成满足需要的sql语句。

mybaits 可以将PreparedStatement中输入参数自动进行输入映射,将查询结果集灵活的映射成java对象(输出对象)

mybatis开发dao两种方法

1.原始的dao开发(程序需要编写dao接口和dao实现类)

2.mybatis的mapper接口(相当于到接口)代理开发方法

原始的dao开发:

流程图



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">

<!--properties中还可以配置一些属性名和属性值  正常测试和异常测试
-->
<!-- <property name="jdbc.driver" value=""/>  在元素体内首先读取的,然后会读取resource 或者url加载的属性,他会覆盖-->

</properties>
<!-- 全局配置参数,需要时再设置 可能需要调整一些比如开启二级缓存,延迟加载  -->
<!-- <settings>

</settings> -->

<!-- 别名定义 -->
<typeAliases>

<!-- 针对单个别名定义
type:类型的路径
alias:别名
方便后面sql输入输出映射的使用
-->
<!-- <typeAlias type="com.mybatis.pojo.UserInfo" alias="userInfo"/> -->
<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)

-->
<package name="com.mybatis.pojo"/>

</typeAliases>
<!--TypeHandler 类型处理器 java类型到JDBC类型转换-->

<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 加载 映射文件 -->
<mappers>

<mapper resource="sqlmap/UserInfo.xml"/>

</mappers>

</configuration>


UserInfo.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">

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
ORM java 对象和关系(数据库的)进行映射

-->
<mapper namespace="test">

<!--id是一个标识,用于开发程序使用  将sql语句封装到mappedStatement对象中,所以将id称为statement的id-->
<!--#{}表示一个占位符号-->
<!--#{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称-->

<!--resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。-->
<select id="findUserInfoById" parameterType="java.lang.Integer" resultType="com.mybatis.pojo.UserInfo">
SELECT * FROM UserInfo WHERE id=#{value}
</select>

<!-- 根据用户名称模糊查询用户信息,可能返回多条
resultType:指定就是单条记录所映射的java对象 类型
${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
使用${}拼接sql,引起 sql注入
${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.pojo.UserInfo">
SELECT * FROM UserInfo WHERE userName LIKE '%${value}%'
</select>

<!-- 添加用户
parameterType:指定输入 参数类型是pojo(包括 用户信息)
#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
-->
<insert id="insertUserInfo" parameterType="com.mybatis.pojo.UserInfo">
<!--

将插入数据的主键返回,返回到user对象中

SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键
keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
resultType:指定SELECT LAST_INSERT_ID()的结果类型

-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>

insert into UserInfo(userName,age) value(#{userName},#{age})
<!--
使用mysql的uuid()生成主键
执行过程:
首先通过uuid()得到主键,将主键设置到user对象的id属性中
其次在insert执行时,从userInfo对象中取出id属性值
-->
<!--  <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into UserInfo(userName,age) value(#{userName},#{age}) -->

</insert>

<!-- 删除 用户
根据id删除用户,需要输入 id值

-->
<delete id="deleteUserInfoById" parameterType="int">
delete from UserInfo where id=#{id}
</delete>

<!-- 根据id更新用户
分析:
需要传入用户的id
需要传入用户的更新信息
parameterType指定userInfo对象,包括 id和更新信息,注意:id必须存在
#{id}:从输入 user对象中获取id属性值
-->
<update id="updateUserInfo" parameterType="userInfo">
update UserInfo set userName=#{userName},age=#{age}
where id=#{id}
</update>

</mapper>


UserInfoDao 接口类
package com.mybatis.dao;

import com.mybatis.pojo.UserInfo;

import java.util.Map;

/**
* Created by hsc on 16/9/4.
*/
public interface UserInfoDao {

public UserInfo findUserInfoById(int id) throws Exception;
public int inserUserInfo(UserInfo userInfo) throws Exception;
public int deleteUserInfoById(int id);
public int updateUserInfo(UserInfo userInfo);
}
UserInfoDao 接口实现类

package com.mybatis.dao.Impl;

import com.mybatis.dao.UserInfoDao;
import com.mybatis.pojo.UserInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.Map;

/**
* Created by hsc on 16/9/4.
*/
public class UserInfoDaoImpl implements UserInfoDao {

private SqlSessionFactory sqlSessionFactory;

public UserInfoDaoImpl(SqlSessionFactory sqlSessionFactory)
{
this.sqlSessionFactory=sqlSessionFactory;
}
public UserInfo findUserInfoById(int id) throws Exception {

SqlSession sqlSession=sqlSessionFactory.openSession();
UserInfo userInfo=  sqlSession.selectOne("test.findUserInfoById",id);
sqlSession.close();

return userInfo;

}

public int inserUserInfo(UserInfo userInfo) throws Exception {

SqlSession sqlSession=sqlSessionFactory.openSession();
int size=  sqlSession.insert("test.insertUserInfo",userInfo);
sqlSession.commit();//插入要做提交
sqlSession.close();

return  size;

}

public int deleteUserInfoById(int id) {

SqlSession sqlSession=sqlSessionFactory.openSession();
int size=  sqlSession.delete("test.deleteUserInfoById",id);
sqlSession.commit();//删除要做提交
sqlSession.close();

return  size;
}

public int updateUserInfo(UserInfo userInfo) {

SqlSession sqlSession=sqlSessionFactory.openSession();
int size=  sqlSession.delete("test.updateUserInfo",userInfo);
sqlSession.commit();//更新要做提交
sqlSession.close();

return size;

}
}


单元测试类

package com.mybatis.Test;

import com.mybatis.dao.Impl.UserInfoDaoImpl;
import com.mybatis.dao.UserInfoDao;
import com.mybatis.pojo.UserInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

/**
* Created by hsc on 16/9/4.
*/
public class UserInfoDaoTest {

private SqlSessionFactory sqlSessionFactory;

@Before
public void  initSqlFactory() throws Exception
{

String res="SqlMapConfig.xml";
InputStream in= Resources.getResourceAsStream(res);
//创建会话工厂
sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
}
@Test
public void testFindUserInfoById() throws Exception
{
UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);

UserInfo userInfo=userInfoDao.findUserInfoById(1);
System.out.println(userInfo.getUserName());
}

@Test
public void testDeleteUserInfoById() throws Exception
{
UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
int size=userInfoDao.deleteUserInfoById(1);
System.out.println(size);

}

@Test
public void testInsertUserInfo() throws Exception
{
UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
UserInfo userInfo=new UserInfo();
userInfo.setAge(18);
userInfo.setUserName("张大雷");

int size=userInfoDao.inserUserInfo(userInfo);
System.out.println(size);
System.out.println(userInfo.getId());

}

@Test
public void testUpateUserInfo() throws Exception
{
UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
UserInfo userInfo=new UserInfo();
userInfo.setAge(14);
userInfo.setUserName("陈大雷");
userInfo.setId(6);
int size=userInfoDao.updateUserInfo(userInfo);

System.out.println(size);

}

}


原始dao开发方法(程序员需要写dao接口和实现类,需要向dao的实现类注入SqlSessionFactory,它是单例,是线程安全的

SqlSession 是线程不安全的,最佳应用场合是方法体内
总结原始dao开发的问题1.dao 接口实现类中存在大量模板或者重复的代码 2.依然存在硬编码

参考资料:传智燕青的课堂笔记

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: