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接口方法的參數只能有一個:這個問題其實很簡單,就是經過包裝類將所須要的多個參數包裝成一個類