1. 一个简单的JDBC程序示例:java
public class JDBCDemo { public static void main(String[] args) { Connection con=null; PreparedStatement statement=null; ResultSet rs=null; try { //首先获取到与数据库的链接对象 Properties pro=new Properties(); pro.load(JDBCDemo3.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); String driver=pro.getProperty("driver"); String user=pro.getProperty("user"); String url=pro.getProperty("url"); String password=pro.getProperty("password"); Class.forName(driver); con=DriverManager.getConnection(url, user, password); //执行sql语句 String id="1"; String sql="select * from employee where id=?"; statement=con.prepareStatement(sql); statement.setInt(1,2); rs=statement.executeQuery(); while(rs.next()){ System.out.println(rs.getInt("id")); System.out.println(rs.getString(2)); System.out.println(rs.getFloat("salary")); System.out.println(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } rs=null; try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } statement=null; try { if(con!=null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } con=null; } } }
2. 上面代码形成的问题:mysql
1. mybatis是一个持久层的框架,是apache下的顶级项目。mybatis让程序将主要精力放在sql上,经过mybatis提供的映射方式,自由灵活生成(半自动化,须要程序员编写sql语句的主体,而sql语句中的字段等参数由mybatis添加)知足须要sql语句。mybatis能够将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象(输出映射)。程序员
2. 框架执行流程:sql
3. 详细介绍及部分原理能够参考:MyBatis的架构设计以及实例分析数据库
1. 编写Mybatis的配置文件:apache
<?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> <settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings> <!-- 与Spring整合后environments标签的全部内容都要删除 --> <environments default="environment"> <environment id="environment"> <!-- 配置JDBC事务管理, mybatis进行事物控制mybatis--> <transactionManager type="JDBC" /> <!-- 配置数据库链接池,使用mybatis提供的--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/cloud_note?useUnicode=true&characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!--指定映射文件位置,与Spring整合后,只须要保存该标签便可--> <mappers> <mapper resource="mapper/Usermapper.xml"/> </mappers> </configuration>
2. 编写User的pojo类,用做输入或输出映射,注意,该pojo类必须符合JavaBean规范,并且类中的属性名要与数据库表中的字段名相同session
import java.io.Serializable; public class User implements Serializable{ private String cn_user_id; private String cn_user_name; private String cn_user_password; private String cn_user_token; private String cn_user_nick; public String getCn_user_id() { return cn_user_id; } public void setCn_user_id(String cn_user_id) { this.cn_user_id = cn_user_id; } public String getCn_user_name() { return cn_user_name; } public void setCn_user_name(String cn_user_name) { this.cn_user_name = cn_user_name; } public String getCn_user_password() { return cn_user_password; } public void setCn_user_password(String cn_user_password) { this.cn_user_password = cn_user_password; } public String getCn_user_token() { return cn_user_token; } public void setCn_user_token(String cn_user_token) { this.cn_user_token = cn_user_token; } public String getCn_user_nick() { return cn_user_nick; } public void setCn_user_nick(String cn_user_nick) { this.cn_user_nick = cn_user_nick; } @Override public String toString() { return "User [cn_user_id=" + cn_user_id + ", cn_user_name=" + cn_user_name + "]"; } }
3. 编写映射文件Mapper.xml:映射文件中包含了Java对象和数据库表之间的映射关系,SQL语句所须要的输入参数映射和输出参数映射都在Mapper.xml中定义,该文件命名必须为*Mapper.xml,好比UserMapper.xmlmybatis
<?xml version="1.0" encoding="UTF-8" ?> <!-- 首先要引入mybatis的标签约束 --> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace属性值表示命名空间,用于SQL的隔离--> <mapper namespace="dao.UserDao"> <!--select标签就表示定义select查询SQL语句,id就表示该语句的标示,当引用该语句时,就经过namespace + .id来引用该SQL语句 --> <select id="findUserById" parameterType="java.lang.String" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} </select> <!--insert标签就表示定义insert插入数据SQL语句 --> <insert id="insertUser" parameterType="entity.User"> <!-- selectKey标签为insert标签特有的子标签,用来将生成的主键回写到传入的pojo对象中 1. keyProperty指定回写的pojo对象中的属性名 2. order指定该回写操做是在SQL语句执行前仍是执行后 3. resultType指定回写的数据映射的Java类型 --> <selectKey keyProperty="cn_user_id" order="BEFORE" resultType="string"> <!-- 经过mysql内置的UUID()函数来生成主键并注入至传入User类型对象的cn_user_id属性中 而后再将此对象做为参数传入sql语句执行 --> select uuid() </selectKey> <!-- 在自增id的数据库中可以使用last_insert_id()函数来获取最后一次执行插入数据的主键id 在执行完SQL语句后,将新插入数据的id返回给对象而且设置为cn_user_id 注意:自增主键的数据库的主键id其类型必须为int型 <selectKey keyProperty="cn_user_id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> --> insert into cn_user(cn_user_id,cn_user_name,cn_user_password,cn_user_token,cn_user_nick) values(#{cn_user_id},#{cn_user_name},#{cn_user_password},#{cn_user_token},#{cn_user_nick}) <!--#{}至关于JDBC代码中的SQL预编译语句中的 ? ,表示占位符,若是接受的参数类型数parameterType 为Java中string、int、long等,则#{}中的字符串能够随便写,但通常建议写为该参数对应的数据库表的字段名; 但若是该参数为自定义的pojo类,如User类,则#{}中的字符串 必须为对应的pojo对象中的属性名,Mybatis会经过OGNL获取pojo对象中对应属性的值--> </insert> <!-- 经过cn_user_name字段进行模糊查询,可能会返回多条数据,可是每条数据所映射的对象仍然是entity.User类,resultType指的是每一条数据所映射的类型 --> <select id="selectUserLike" parameterType="string" resultType="entity.User"> <!-- 该方式是将%写在SQL语句中,那么代码中就不用在传入的字符串两端添加% --> select * from cn_user where cn_user_name like '%#{name}%' <!-- 该方式是在代码对传入的参数字符串两端添加% --> <!-- select * from cn_user where cn_user_name like '#{name}' --> </select> </mapper>
4. 编写测试程序:架构
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.Before; import org.junit.Test; import entity.User; //Mybatis框架底层实现数据库交互操做过程 public class TestCase1 { private SqlSessionFactory ssf; @Before public void init() throws IOException{ //1.实例SqlSessionFactoryBuilder String resource="conf/SqlMapConfig.xml"; InputStream s=Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder ssfb=new SqlSessionFactoryBuilder(); //2.经过SqlSessionFactoryBuilder对象加载mybatis环境配置文件,获取SqlSessionFactory对象 ssf=ssfb.build(s); } @Test public void testFindUserbyId(){ //3.经过SqlSessionFactory对象来获取SqlSession对象,与数据库进行交互 SqlSession session=ssf.openSession(); User user=session.selectOne("dao.UserDao.findUserById", "03590914-a934-4da9-ba4d-b41799f917d1"); System.out.println(user.toString()); session.close(); } @Test public void testInsertUser(){ User user=new User(); user.setCn_user_name("hop"); user.setCn_user_password("123546"); SqlSession session=ssf.openSession(); session.insert("dao.UserDao.insertUser", user); System.out.println(user.toString());//查看回写的用户id session.close(); } @Test public void testSelectUserLike(){ SqlSession session=ssf.openSession(); List<User> list=session.selectList("dao.UserDao.selectUserLike", "测试"); //List<User> list=session.selectList("dao.UserDao.selectUserLike", "%测试%"); session.close(); } }
5. 关于Mapper映射文件中的部分重点讲解:app
若是输入参数类型为pojo类,并且该类中还包括一个pojo类型的属性,#{}接收pojo对象值,经过OGNL读取对象中的属性值,经过属性.属性.属性...的方式获取对象属性值,好比输入参数类型为User类,User类内还有一个book属性,该属性为Book类,是一个pojo类,Book类中包括String类型的name属性,那么若是要取name属性值,就能够写为#{book.name}。
1. 定义Dao接口:
import entity.User; public interface UserDao { public User findUserById(String id); public void insertUser(User user); }
2. 经过Mybatis开发Dao接口的实现类:
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.Before; import entity.User; public class UserDaoImp implements UserDao { private static SqlSessionFactory ssf; static{ String resource="conf/SqlMapConfig.xml"; InputStream s; try { s = Resources.getResourceAsStream(resource); ssf=new SqlSessionFactoryBuilder().build(s); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public User findUserById(String id) { SqlSession session=ssf.openSession(); User user=session.selectOne("findUserById",id); session.close(); return user; } @Override public void insertUser(User user) { SqlSession session=ssf.openSession(); session.insert("insertUser", user); session.close(); } }
3. 原始dao开发存在的问题:
1. 该只须要编写好Mapper接口(Mapper接口也就是Dao接口),定义数据操做方法便可,编写mapper接口须要遵循一些开发规范,mybatis能够自动生成mapper接口实现类代理对象。
2. 开发规范有:
package dao; import entity.User; public interface UserDao { public User findUserById(String id); public void insertUser(User user); }
<?xml version="1.0" encoding="UTF-8" ?> <!-- 首先要引入mybatis的标签约束 --> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> </mapper>
<?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="dao.UserDao"> <select id="findUserById" parameterType="java.lang.String" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} </select> <insert id="insertUser" parameterType="entity.User"> <selectKey keyProperty="cn_user_id" order="BEFORE" resultType="string"> select uuid() </selectKey> insert into cn_user(cn_user_id,cn_user_name,cn_user_password,cn_user_token,cn_user_nick) values(#{cn_user_id},#{cn_user_name},#{cn_user_password},#{cn_user_token},#{cn_user_nick}) </insert> </mapper>
3. 知足以上开发规范后,可经过测试代码验证:
/** * 测试Mybatis框架经过Mapper代理方法实现Dao接口 */ public class TestCase3 { private SqlSessionFactory ssf; @Before public void init() throws IOException{ String resource="conf/SqlMapConfig.xml"; InputStream s=Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder ssfb=new SqlSessionFactoryBuilder(); ssf=ssfb.build(s); } @Test public void testFindUserbyId(){ SqlSession session=ssf.openSession(); UserDao dao=session.getMapper(UserDao.class); User user=dao.findUserById("03590914-a934-4da9-ba4d-b41799f917d1"); System.out.println(user.toString()); } }
4. Mapper接口方法的参数只能有一个:这个问题其实很简单,就是经过包装类将所须要的多个参数包装成一个类