兩個都是持久層框架,操做數據庫,可是二者仍是有區別的 java
hibernate:它是一個標準的orm框架,比較重量級,學習成本高.
優勢:高度封裝,使用起來不用寫sql,開發的時候,會減低開發週期.
缺點:sql語句沒法優化
應用場景:oa(辦公自動化系統), erp(企業的流程系統)等,還有一些政府項目,
總的來講,在用於量不大,併發量小的時候使用.
mybatis:它不是一個orm框架, 它是對jdbc的輕量級封裝, 學習成本低,比較簡單
優勢:學習成本低, sql語句能夠優化, 執行效率高,速度快
缺點:編碼量較大,會拖慢開發週期
應用場景: 互聯網項目,好比電商,P2p等
總的來講是用戶量較大,併發高的項目。mysql
此時操做數據庫,須要引入數據庫驅動,這裏我使用的是mysql驅動git
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //加載數據庫驅動 Class.forName("com.mysql.jdbc.Driver"); //經過驅動管理類獲取數據庫連接 connection = DriverManager.getConnection("jdbc:mysql://192.168.174.130:3306/SSM", "root", "root"); //定義sql語句 ?表示佔位符 String sql = "select * from myUser where username = ?"; //獲取預處理statement preparedStatement = connection.prepareStatement(sql); //設置參數,第一個參數爲sql語句中參數的序號(從1開始),第二個參數爲設置的參數值 preparedStatement.setString(1, "王五"); //向數據庫發出sql執行查詢,查詢出結果集 resultSet = preparedStatement.executeQuery(); //遍歷查詢結果集 while(resultSet.next()){ System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
缺點:頻繁建立釋放資源下降性能;代碼耦合性強,不易維護;傳參與所獲結果集編碼不夠靈活(存在硬編碼)github
綜上:mybatis解決了以上問題spring
一、在SqlMapConfig.xml中配置數據連接池,使用鏈接池管理數據庫連接,大大減小了不斷建立釋放資源。sql
二、將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。數據庫
三、Mybatis自動將java對象映射至sql語句,經過statement中的parameterType定義輸入參數的類型。解決了條件查詢中笨重問題express
mybatis官網: http://www.mybatis.org/mybatis-3/apache
jar包下載地址: https://github.com/mybatis/mybatis-3/releasesapi
# 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
配置文件中主要是配置鏈接數據庫和事務管理的內容,文件名能夠自定義,默認SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://www.mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 和spring整合後 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理--> <transactionManager type="JDBC" /> <!-- 數據庫鏈接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://192.168.174.130:3306/SSM" /> <!--注意:這裏必須是username,必定要規範--> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> </configuration>
與hibernate想區別的是:hibernate是經過操做映射文件對象來操做數據庫,與sql無太大關係;mybatis的映射文件是用來寫sql語句的
注意:此文件放在源碼包下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd">
<!-- namespace命名空間,作sql隔離,防止命名重複 -->
<mapper namespace="test">
</mapper>
<mappers>
<mapper resource="User.xml"/> </mappers>
此時環境差很少就部署好了
5、需求開發
一、根據id查詢一個客戶
1)創建客戶表
2)定義pojo類
package com.clj.pojo; import java.util.Date; import java.util.List; public class User { private int id; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 private List<Orders> ordersList; public List<Orders> getOrdersList() { return ordersList; } public void setOrdersList(List<Orders> ordersList) { this.ordersList = ordersList; } 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 + "]"; } }
3)在User.xml文件中配置sql語句
注意:當傳入參數類型時原始型時,佔位符中的括號中的值能夠隨意設置,但最好可讀性較強(佔位符能自動進行java類型和jdbc類型轉換,能夠有效防止sql注入。)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!-- namespace命名空間,作sql隔離 --> <mapper namespace="test"> <!-- id:sql語句惟一標識 parameterType:指定傳入參數類型(對應javaBean類型,寫原始型會自動包裝爲包裝類) resultType:返回結果類型 #{}:佔位符號,起到佔位做用,若是傳入的是原始型,那麼括號中的變量名稱能夠隨意定義 --> <select id="findUserById" parameterType="int" resultType="com.clj.pojo.User"> select * from user where id=#{id} </select> </mapper>
3)測試
值得注意的是,這裏調用sql的寫法
@Test public void testFindUserById() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputStream=Resources.getResourceAsStream(resource); //建立工廠 SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream); //經過工廠建立會話 SqlSession openSession=factory.openSession(); //第一個參數:所調用的sql語句:namespace+‘.’+SqlID //第二個參數:傳入的參數 User user=openSession.selectOne("test.findUserById",1); System.out.println(user); openSession.close(); }
這裏調用的是selectOne方法,旨在查詢一條指定的數據,若是用它查詢多條數據,會報異常(查詢多條要用selectList)
1)在User.xml文件中配置sql語句
注意:當傳入的參數是非引用型時,拼接符要用"value"(拼接符不進行jdbc類型轉換, ${}能夠接收簡單類型值或pojo屬性值,若是parameterType傳輸單個簡單類型值,${}括號中只能是value。)
這裏返回值爲List集合,配置爲該集合的泛型
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!-- namespace命名空間,作sql隔離 --> <mapper namespace="test"> <!-- 若是返回結果爲集合,能夠調用selectList方法。這個方法返回結果就有個集合 , 因此映射文件應該配置成集合的泛型 ${}拼接符:字符串原樣拼接,若是傳入的參數是基本類型,括號中的值必須爲「value」 注意:拼接符有sql注入的風險,因此慎用(=號用佔位符,like用拼接符)--> <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.clj.pojo.User"> <!--select * from user where username like #{name} --> select * from user where username like '%${value}%' </select> </mapper>
2)測試
@Test public void testFindUSerByUserName() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); //List<User> list=openSession.selectList("test.findUserByUserName","%王%"); List<User> list=openSession.selectList("test.findUserByUserName","王"); System.out.println(list); openSession.close(); }
1)配置sql
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!-- namespace命名空間,作sql隔離 --> <mapper namespace="test"> <!-- #{}:若是傳入的是pojo類型,那麼#{}中變量的名稱必須是pojo中對應的屬性 若是要返回數據庫自增主鍵,可使用select LAST_INSERT_ID() --> <insert id="insertUser" parameterType="com.clj.pojo.User"> <!-- 執行 LAST_INSERT_ID,返回自增的主鍵 keyProperty:將返回的主鍵放入傳入參數的ID中保存 order:至關於insert語句的執行順序,在insert前執行時before,以後是after resultType:keyProperty中屬性的類型, --> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
注意:這裏添加selectKey實現將主鍵返回,由於是先插入數據,才能得到主鍵,因此其屬性值order="AFTER"
若是是uuid(隨機字符串),屬性值order="Before"
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey resultType="java.lang.String" order="BEFORE" keyProperty="id"> select uuid() </selectKey> insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address}) </insert>
2) 測試
@Test public void testInsertUser() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); User user=new User(); user.setUsername("趙四"); user.setBirthday(new Date()); user.setSex("1"); user.setAddress("長沙市"); System.out.println("======"+user.getId()); openSession.insert("test.insertUser",user); //提交事務(mybatis會自動提交事務,可是不知道什麼時候手動提交事務) openSession.commit(); System.out.println("========"+user.getId()); openSession.close(); }
1)配置sql語句
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!-- namespace命名空間,作sql隔離 --> <mapper namespace="test"> <delete id="delUserById" parameterType="int"> delete from user where id=#{id} </delete> <update id="updateUserById" parameterType="com.clj.pojo.User"> update user set username=#{username} where id=#{id} </update> </mapper>
2)測試
@Test public void testDelUserById() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); openSession.delete("test.delUserById",29); openSession.commit(); openSession.close(); } @Test public void testUpdateUserById()throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); User user=new User(); user.setId(28); user.setUsername("佳先森"); openSession.update("test.updateUserById",user); openSession.commit(); openSession.close(); }
擴展:將鏈接數據庫中的屬性封裝到數據庫配置文件中
jdbc.driver=com.mysql.jdbc.Driver\t jdbc.url=jdbc:mysql://192.168.174.130:3306/SSM jdbc.username=root jdbc.password=root
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://www.mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 引入連接數據庫配置文件 --> <properties resource="db.properties"/> <!-- 和spring整合後 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理--> <transactionManager type="JDBC" /> <!-- 數據庫鏈接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <!--注意:這裏必須是username,必定要規範--> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <mappers><mapper resource="User.xml"/> </mappers> </configuration>
在覈心配置文件中第一個類的別名,後面能夠直接引用別名,無需配置全路徑
<typeAliases> <!-- 定義單個pojo類別名 type:類的全路徑名稱 alias:別名 --> <typeAlias type="com.clj.pojo.User" alias="user"/> <!-- 使用包掃描的方式批量定義別名,定義後別名等於類名 ,不區分大小寫 ,但最好按照駝峯命名法書寫--> <package name="com.clj.pojo"/> </typeAliases>
有兩種寫法:一種是單個引入,另外一種是包掃描的方式
<mappers> <!-- 兩種引入方式 方式一:單個引入 <mapper resource="User.xml"/>--> <!-- 使用class屬性引入接口的全路徑名稱: 使用規則:1.接口名稱和映射文件名稱除擴展名以外要徹底相同 2.接口和映射文件要放在同一個目錄下 <mapper class="com.clj.UserMapper.UserMapper"/>--> <!-- 方式二:使用包掃描的方式批量引入Mapper 使用包掃描規則和上個同樣 --> <package name="com.clj.UserMapper"/> </mappers>
MyBatis之Dao層的開發方式有兩種:原始Dao開發和Mapper接口開發
1)配置user.xml中的sql語句
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!-- namespace命名空間,作sql隔離 --> <mapper namespace="test"> <select id="findUserById" parameterType="int" resultType="com.clj.pojo.User"> select * from user where id=#{id} </select> <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.clj.pojo.User">
select * from user where username like '%${value}%'
</select>
</mapper>
2)定義接口和實現類
package com.clj.dao; import java.util.List; import com.clj.pojo.User; public interface UserDao { public User findUserById(Integer id); public List<User> findUserByUserName(String username); }
package com.clj.dao; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import com.clj.pojo.User; public class UserDaoImpl implements UserDao{ private SqlSessionFactory sqlSessionFactory; //經過構造方法注入 public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { super(); this.sqlSessionFactory = sqlSessionFactory; } @Override public User findUserById(Integer id) { //SqlSession是線程不安全的,因此他的最佳使用的範圍在方法體內 SqlSession opeanSession=sqlSessionFactory.openSession(); User user=opeanSession.selectOne("test.findUserById",id); return user; } @Override public List<User> findUserByUserName(String username) { SqlSession opeanSession=sqlSessionFactory.openSession(); List<User> list=opeanSession.selectList("test.findUserByUserName",username); return list; } }
3)在覈心配置文件SqlMapConfig.xml中引入user.xml
<mappers>
<mapper resource="User.xml"/> </mappers>
4)定義測試類進行測試
package com.clj.Test; 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 com.clj.dao.UserDao; import com.clj.dao.UserDaoImpl; import com.clj.pojo.User; public class UserDaoTest { private SqlSessionFactory factory; //@Before做用在測試方法以前執行這個方法 @Before public void setUp() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); } @Test public void testFindUserById() throws Exception{ //將初始化的工廠注入到實現類中 UserDao userDao=new UserDaoImpl(factory); User user=userDao.findUserById(1); System.out.println(user); } @Test public void testFindUserByUserName() throws Exception{ UserDao userDao=new UserDaoImpl(factory); List<User> list=userDao.findUserByUserName("王"); System.out.println(list); } }
總結:原始Dao仍是存在一些很差的因素:1.代碼有重複 2.sqlSession調用sql時須要指定id值,存在硬編碼
Mapper動態代理的方式須要嚴格遵照一些規範
需求一:經過主鍵查找用戶;經過用戶名查找用戶;插入用戶數據
1)定義接口
package com.clj.UserMapper; import java.util.List; import com.clj.pojo.CustomerOrders; import com.clj.pojo.Orders; import com.clj.pojo.QueryVo; import com.clj.pojo.User; //與之關乎的配置文件要在同一個目錄包下 public interface UserMapper { public User findUserById(Integer id); //注意:這裏是模糊查詢,配置文件雖然寫的是User,實際返回的是List集合 //動態代理形式中,若是返回結果集List,那麼mybatis會在生成實現類的時候會自動調用selectList方法 public List<User> findUserByUserName(String userName); public void insertUser(User user); }
2)定義其映射文件,最好是在同目錄下
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="com.clj.pojo.User"> select * from user where id=#{id} </select> <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.clj.pojo.User"> <!--select * from user where username like #{name} --> select * from user where username like '%${value}%' </select> <!-- 這裏返回值使用的別名 --> <insert id="insertUser" parameterType="user"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
兩文件的目錄關係
3)在覈心配置文件中引入Mapper的配置文件
<mappers> <!-- 兩種引入方式 方式一:單個引入 <mapper resource="User.xml"/>--> <!-- 方式二:使用包掃描的方式批量引入Mapper 使用包掃描規則和上個同樣 --> <package name="com.clj.UserMapper"/> </mappers>
·4)測試類
package com.clj.Test; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; 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 com.clj.UserMapper.UserMapper; import com.clj.pojo.CustomerOrders; import com.clj.pojo.Orders; import com.clj.pojo.QueryVo; import com.clj.pojo.User; public class UserMapperTest { private static SqlSessionFactory factory; //@Before做用在測試方法以前執行這個方法 @Before public void setUp() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); } @Test public void testFindUserById() throws Exception{ SqlSession openSession=factory.openSession(); //經過getMapper方法實列化接口 UserMapper mapper=openSession.getMapper(UserMapper.class); User user=mapper.findUserById(1); System.out.println(user); } }
另外:刪除用戶和更新用戶sql配置文件方式爲,具體步驟如上
<delete id="delUserById" parameterType="int"> delete from user where id=#{id} </delete> <update id="updateUserById" parameterType="com.clj.pojo.User"> update user set username=#{username} where id=#{id} </update>
需求二:根據用戶名查詢,利用高級查詢Vo類
1)建立Vo類封裝用戶屬性,並提供set/get方法
package com.clj.pojo; import java.util.List; //用於高級查詢 public class QueryVo { private User user; private List<Integer> ids; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; } }
2)在UserMapper.xml文件中配置查詢語句
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <select id="findUserbyVo" parameterType="com.clj.pojo.QueryVo" resultType="com.clj.pojo.User"> select * from user where username like '%${user.username}%' and sex=#{user.sex} </select> </mapper>
3)定義接口
public List<User> findUserbyVo(QueryVo vo);
4)測試類
public class UserMapperTest { private static SqlSessionFactory factory; //@Before做用在測試方法以前執行這個方法 @Before public void setUp() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); } @Test public void testFindUserByVo() throws Exception{ SqlSession openSession=factory.openSession(); //經過getMapper方法實列化接口 UserMapper mapper=openSession.getMapper(UserMapper.class); QueryVo vo=new QueryVo(); User user=new User(); user.setUsername("張"); user.setSex("1");
vo.setUser(user); List<User> list=mapper.findUserbyVo(vo); System.out.println(list); openSession.close(); } }
需求三:查詢數據總數,利用count(*)
1) 配置sql
<!-- 只有返回結果爲一行一列的時候,那麼返回值類型時能夠指定類型爲基本類型 --> <select id="findUserCount" resultType="int"> select count(*) from user </select>
2) 配置接口
public Integer findUserCount();
3)測試
@Test public void testFindUserCount()throws Exception{ SqlSession opneSession=factory.openSession(); //經過getMapper方法實例化接口 UserMapper mapper=opneSession.getMapper(UserMapper.class); Integer count=mapper.findUserCount(); System.out.println("===="+count); }
需求四:動態增長查詢條件
1)配置sql
方式一:局部配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <select id="findUserByUserNameAndSex" parameterType="com.clj.pojo.User" resultType="com.clj.pojo.User"> select * from user <!-- where標籤做用: 會自動向sql語句中添加where關鍵字 會去掉第一個條件的and關鍵字 --> <where> <if test="username!=null and username !=''"> and username like '%${username}%' </if> <if test="sex !=null and sex!=''"> and sex=#{sex} </if> </where> </select> </mapper>
方式二:全局配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <!-- 封裝sql條件,封裝後能夠重用 id:此sql的惟一標識符 --> <sql id="user_where"> <where> <if test="username!=null and username !=''"> and username like '%${username}%' </if> <if test="sex !=null and sex!=''"> and sex=#{sex} </if> </where> </sql> <select id="findUserByUserNameAndSex" parameterType="com.clj.pojo.User" resultType="com.clj.pojo.User"> select * from user <!-- where標籤做用: 會自動向sql語句中添加where關鍵字 會去掉第一個條件的and關鍵字 <where> <if test="username!=null and username !=''"> and username like '%${username}%' </if> <if test="sex !=null and sex!=''"> and sex=#{sex} </if> </where>--> <!-- 調用全局條件 --> <include refid="user_where"/> </select> </mapper>
2)接口
public List<User> findUserByUserNameAndSex(User user);
3)測試
@Test public void testFindUserbyUserNameAndSex() throws Exception{ SqlSession opneSession=factory.openSession(); UserMapper mapper=opneSession.getMapper(UserMapper.class); User user=new User(); user.setUsername("張"); user.setSex("1"); List<User> list=mapper.findUserByUserNameAndSex(user); System.out.println(list); }
需求五:查詢主鍵在某個範圍內(動態添加條件查詢之foreach標籤)
1)sql配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <select id="findUserByIds" parameterType="com.clj.pojo.QueryVo" resultType="com.clj.pojo.User"> <!-- select * from user where id in (1,16,28,22) --> select * from user <where> <!-- 這裏的id指定是vo中的集合屬性 --> <if test="ids!=null"> <!-- foreach:循環傳入的集合參數 collection:傳入的集合的變量名稱 item:每次循環將循環的數據放入這個變量中 open:循環開始拼接的字符串 close:循環結束拼接的字符串 separator:循環中拼接的分隔符 --> <foreach collection="ids" item="id" open="id in (" close=")" separator=","> #{id} </foreach> </if> </where> </select> </mapper>
2)接口
public List<User> findUserByIds(QueryVo vo);
3)測試
public class UserMapperTest { private static SqlSessionFactory factory; //@Before做用在測試方法以前執行這個方法 @Before public void setUp() throws Exception{ String resource="SqlMapConfig.xml"; InputStream inputstream=Resources.getResourceAsStream(resource); factory=new SqlSessionFactoryBuilder().build(inputstream); SqlSession openSession=factory.openSession(); } @Test public void testFindUserbyIds() throws Exception{ SqlSession opneSession=factory.openSession(); UserMapper mapper=opneSession.getMapper(UserMapper.class); QueryVo vo=new QueryVo(); List<Integer> ids=new ArrayList<Integer>(); ids.add(1); ids.add(16); ids.add(28); ids.add(22); List<User> list=mapper.findUserByIds(vo);System.out.println(list); } }
需求六:關聯查詢之一對一查詢
環境:一個客戶對應多個訂單,而一個訂單對應一個客戶
方法一:使用resultType,定義訂單信息po類,此po類中包括了訂單信息和用戶信息
1)預測sql語句寫法:SELECT orders.*,user.username,userss.address FROM orders,user WHERE orders.user_id = user.id
2)定義訂單類
package com.clj.pojo; import java.util.Date; public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number == null ? null : number.trim(); } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note == null ? null : note.trim(); } }
3)定義封裝客戶和訂單的pojo類,此類包含上邊預測的sql語句字段
package com.clj.pojo; import java.util.Date; //一對一:select a.*,b.id uid,username,birthday,sex,address //from order a,user b //where a.user_id=b.id //注意:不能用實體User代替他屬性 //缺點:java是單繼承 public class CustomerOrders extends Orders{ private int uid; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } 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; } }
注意:OrdersCustom類繼承Orders類後OrdersCustom類包括了Orders類的全部字段,只須要定義用戶的信息字段便可。(注意:這裏不能用user來取代這些屬性)
4)配置sql語句
1)在order類中定義user屬性
package com.clj.pojo; import java.util.Date; public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number == null ? null : number.trim(); } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note == null ? null : note.trim(); } }
2)配置sql語句
<!-- 關於一對一查詢 --> <!-- 方式一:自動映射 :利用類中的屬性對應表中的字段 須要提供封裝user和order屬性的類--> <select id="findOrderAndUser1" resultType="com.clj.pojo.CustomerOrders"> select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id=b.id </select>
5)配置接口
public List<CustomerOrders> findOrderAndUser1();
6)定義測試類
@Test public void testFindORdersAndUser() throws Exception{ SqlSession opneSession=factory.openSession(); UserMapper mapper=opneSession.getMapper(UserMapper.class); List<CustomerOrders> list=mapper.findOrderAndUser1(); System.out.println(list); }
總結:此方法雖然簡單,定義專門的pojo類做爲輸出類型,其中定義了sql查詢結果集全部的字段。可是缺點是pojo類只能單繼承
方式二:使用resultMap,定義專門的resultMap用於映射一對一查詢結果
1)配置sql 注意此時不須要CustomerOrders 類
<!-- 一對一:手動映射:須要在order類中封裝User這個屬性 --> <!-- id:resultMap的惟一標識 type:將查詢出的數據放入指定的對象中 注意:手動映射須要指定數據表中的字段名與java中pojo類中的屬性名稱對應的關係 --> <resultMap type="com.clj.pojo.Orders" id="orderAndUserResultMap"> <!--id標籤指定主鍵字段對應關係 column:列,數據庫中的字段名稱 property:屬性,java中pojo中的屬性名稱 --> <id column="id" property="id"/> <!-- result:指定 非主鍵對應的關係--> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- association:表示進行關聯查詢單條記錄
這個標籤指定單個對象的對應關係 property:表示關聯查詢的結果存儲在cn.itcast.mybatis.po.Orders的user屬性中 javaType:user屬性中類型的路徑 --> <association property="user" javaType="com.clj.pojo.User">
<!--查詢結果的user_id列對應關聯對象的id屬性,這裏是<id />表示user_id是關聯查詢對象的惟一標識--> <id column="uid" property="id"/>
<!--查詢結果的username列對應關聯對象的username屬性--> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> </association> </resultMap> <select id="findOrderAndUser2" resultMap="orderAndUserResultMap"> select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id=b.id </select>
2)配置接口
public List<Orders> findOrderAndUser2();
3)測試類
@Test public void findOrderAndUser2() throws Exception{ SqlSession opneSession=factory.openSession(); UserMapper mapper=opneSession.getMapper(UserMapper.class); List<Orders> list=mapper.findOrderAndUser2(); for(Orders order:list){ System.out.println(order.getUserId()+"\t"+order.getCreatetime()); } }
需求七:一對多查詢
1)預測sql語句
SELECT u.*, o.id oid,o.number,o.createtime,o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id
2)在user pojo類中加上List集合屬性
package com.clj.pojo; import java.util.Date; import java.util.List; public class User { private int id; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 private List<Orders> ordersList; public List<Orders> getOrdersList() { return ordersList; } public void setOrdersList(List<Orders> ordersList) { this.ordersList = ordersList; } 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 + "]"; } }
3)配置sql
<!-- 一對多 --> <resultMap type="com.clj.pojo.User" id="userAndOrderMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> <!-- 指定對應的集合對象關係映射 property:將數據放入User對象中的orderList屬性中 ofType:指定orderList屬性泛型類型 --> <collection property="ordersList" ofType="com.clj.pojo.Orders"> <id column="oid" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 注意:這裏不須要配置user屬性,他是用於一對一時配置的屬性,與這裏無關 --> </collection> </resultMap> <select id="findUserAndOrders" resultMap="userAndOrderMap"> select a.*,b.id oid,user_id,number,createtime from user a,order b where a.id=b.user_id </select>
4)定義接口
public List<User> findUserAndOrders();
5)測試類
@Test public void findUserAndOrders() throws Exception{ SqlSession opneSession=factory.openSession(); UserMapper mapper=opneSession.getMapper(UserMapper.class); List<User> list=mapper.findUserAndOrders(); System.out.println(list); }
SqlSessionFactory對象應該放到spring容器中做爲單例存在。
傳統dao的開發方式中,應該從spring容器中得到sqlsession對象。
Mapper代理形式中,應該從spring容器中直接得到mapper的代理對象。
數據庫的鏈接以及數據庫鏈接池事務管理都交給spring容器來完成。
1)導入所需jar包
在導入spring包和mybaits包以外還要jar二者的整合包
至於maven構建項目,其pom文件的約束爲:
注意:至於jdbc能夠用c3p0,也能夠用dbcp,可是不管這兩個都須要用到spring-jdbc的jar包,不然會報錯誤
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1570) ... 41 more
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.8</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aopalliance/com.springsource.org.aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/org.aspectj.weaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.17.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.17.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency>
2)在工程項目下(非src)建立一個源碼包,用來存放配置文件
配置鏈接數據庫驅動配置文件db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://192.168.174.130:3306/SSM jdbc.username=root jdbc.password=root
1))配置日誌配置文件log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
配置spring的配置文件applicationContext.xml
1)))配置數據庫驅動,加載db.properties文件
<!-- 加載配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 數據庫鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.password}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
2)))將sqlSessionfactory的建立交給spring管理
<!-- 整合後會話工廠歸spring來管理 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
<!-- 指定會話工廠使用的數據源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
所有代碼以下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 加載配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 數據庫鏈接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 整合後會話工廠歸spring來管理 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
<!-- 指定會話工廠使用的數據源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
其中org.mybatis.spring.SqlSessionFactoryBean的路徑配置以下圖
2)) 配置mybatis數據sql映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://www.mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.clj.pojo"/> </typeAliases> <mappers> <mapper resource="User.xml"/> <package name="com.clj.UserMapper"/> </mappers> </configuration>
1)開發方式一之傳統dao開發
1))思路:
想爲接口+實現類來完成。須要dao實現類須要繼承SqlsessionDaoSupport類
2))接口定義和javaBean
這裏定義了根據id查詢和根據用戶名查詢兩個方法package com.clj.dao;
import java.util.List; import com.clj.pojo.User; public interface UserDao { public User findUserById(Integer id); public List<User> findUserByUserName(String username);
public List<UserBean> findUserByUserNameAndMoney(UserBean userBean);
public List<UserBean> findUserById(QueryVo vo);
}
@Component public class UserBean { private Integer id; private String username; private String age; private Integer money; //set/get方法 }
@Component public class QueryVo { private List<Integer> ids; }
3))實現類定義
實現類實現SqlSessionDaoSupport
package com.clj.dao; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.support.SqlSessionDaoSupport; import com.clj.pojo.User; //此時dao層要繼承SqlSessionDaoSupport public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{ @Override public User findUserById(Integer id) { //SqlSession是線程不安全的,因此他的最佳使用的範圍在方法體內 SqlSession opeanSession=this.getSqlSession(); User user=opeanSession.selectOne("test.findUserById",id); //opeanSession.close(); return user; } @Override public List<User> findUserByUserName(String username) { SqlSession opeanSession=this.getSqlSession(); List<User> list=opeanSession.selectList("test.findUserByUserName",username); return list; }
public List<UserBean> findUserByUserNameAndMoney(UserBean userBean) {
SqlSession sqlSession=this.getSqlSession();
List<UserBean> user=sqlSession.selectList("test.findUserByUserNameAndMoney",userBean);
return user;
}
@Override
public List<UserBean> findUserById(QueryVo vo) {
SqlSession sqlSession=this.getSqlSession();
List<UserBean> user=sqlSession.selectList("test.findUserById",vo);
return user;
}
}
4)) 注入dao層於sprign配置文件(applicationContext.xml)
這裏爲dao層注入了sqlSessionFactory
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 加載配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 數據庫鏈接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean>
<context:component-scan base-package="com.aliance.entity"/> <!-- 整合後會話工廠歸spring來管理 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 指定mybatis核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml"></property> <!-- 指定會話工廠使用的數據源 --> <property name="dataSource" ref="dataSource"/> </bean> <!--配置原生Dao實現 --> <bean id="userDao" class="com.clj.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
5))SqlMap.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>
<typeAliases>
<typeAlias type="com.aliance.entity.UserBean" alias="userBean"/>
</typeAliases>
<mappers>
<mapper resource="User.xml"/>
</mappers>
</configuration>
6))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 id="testWhere"> <where> <if test="username!=null||username!=''"> and username like '%${username}%' </if> <if test="age!=null"> and age> #{age} </if> </where> </sql> <select id="findUserByUserNameAndMoney" parameterType="userBean" resultType="userBean"> select * from userinfo <include refid="testWhere"/> </select> <select id="findUserById" parameterType="com.aliance.entity.QueryVo" resultType="userBean"> select * from userinfo <where> <if test="ids!=null"> <foreach collection="ids" item="id" open="and id in (" close=")" separator=","> #{id} </foreach> </if> </where> </select> </mapper>
6)) 測試類
方式一:
package com.clj.Test; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.clj.dao.UserDao; import com.clj.pojo.User; public class UserDaoTest { private ApplicationContext applicationContext; @Before public void setUp() throws Exception{ //這裏可加classpath,也可不加 String configLocation="classpath:applicationContext.xml"; applicationContext=new ClassPathXmlApplicationContext(configLocation); } @Test public void testFindUserById() throws Exception{ //獲取UserDao對象,getBean中的字符串是在applcationContext.xml中神明的 UserDao userDao=(UserDao)applicationContext.getBean("userDao"); User user=userDao.findUserById(1); System.out.println(user); } }
方式二:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:ApplicationContext.xml") public class TestDemo1 { @Resource private ApplicationContext application; @Resource private UserBean userBean; @Resource private UserDao userDao; @Resource private QueryVo vo; @Test public void run2(){ userDao=(UserDao) application.getBean("userDao"); userBean.setUsername("李"); userBean.setAge("11"); List<UserBean> list=userDao.findUserByUserNameAndMoney(userBean); System.out.println(list); } @Test public void run3(){ userDao=(UserDao) application.getBean("userDao"); List<Integer> list=new ArrayList(); list.add(1); list.add(3); list.add(6); vo.setIds(list); List<UserBean> temp=userDao.findUserById(vo); System.out.println(temp); } }
注意:這裏因爲sqlSessionFactory歸spring管理,因此其關閉也是有spring管理,若是在測試中手動關閉session,會報錯
2)開發方式二:Mapper代理形式開發dao
1))新建一個mapper包,用來配置mapper的接口和配置文件
mapper接口:這裏和整合前mybatis中動態mapper代理接口代碼一致
package com.clj.UserMapper; import java.util.List; import com.clj.pojo.CustomerOrders; import com.clj.pojo.Orders; import com.clj.pojo.QueryVo; import com.clj.pojo.User; //與之關乎的配置文件要在同一個目錄包下 public interface UserMapper { public User findUserById(Integer id); //注意:這裏是模糊查詢,配置文件雖然寫的是User,實際返回的是List集合 //動態代理形式中,若是返回結果集List,那麼mybatis會在生成實現類的時候會自動調用selectList方法 public List<User> findUserByUserName(String userName); public void insertUser(User user); public List<User> findUserbyVo(QueryVo vo); public Integer findUserCount(); public List<User> findUserByUserNameAndSex(User user); public List<User> findUserByIds(QueryVo vo); public List<CustomerOrders> findOrderAndUser1(); public List<Orders> findOrderAndUser2(); public List<User> findUserAndOrders(); }
2))配置sql映射文件:這裏和整合前mybatis中動態mapper代理接口代碼一致
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3.0-mapper.dtd"> <!--mapper接口代理實現編寫軌則 1.映射文件中namespace要等於接口的全路徑名 2.映射文件中sql語句id要等於接口的方法名稱 3.映射文件中傳入參數類型要等於接口方法的傳入參數類型 4.映射文件中返回結果集類型等於接口方法的返回值類型 --> <mapper namespace="com.clj.UserMapper.UserMapper"> <!-- 封裝sql條件,封裝後能夠重用 id:此sql的惟一標識符 --> <sql id="user_where"> <where> <if test="username!=null and username !=''"> and username like '%${username}%' </if> <if test="sex !=null and sex!=''"> and sex=#{sex} </if> </where> </sql> <select id="findUserById" parameterType="int" resultType="com.clj.pojo.User"> select * from user where id=#{id} </select> <select id="findUserByUserName" parameterType="java.lang.String" resultType="com.clj.pojo.User"> <!--select * from user where username like #{name} --> select * from user where username like '%${value}%' </select> <!-- 這裏返回值使用的別名 --> <insert id="insertUser" parameterType="user"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> <delete id="delUserById" parameterType="int"> delete from user where id=#{id} </delete> <update id="updateUserById" parameterType="com.clj.pojo.User"> update user set username=#{username} where id=#{id} </update> <select id="findUserbyVo" parameterType="com.clj.pojo.QueryVo" resultType="com.clj.pojo.User"> select * from user where username like '%${user.username}%' and sex=#{user.sex} </select> <!-- 只有返回結果爲一行一列的時候,那麼返回值類型時能夠指定類型爲基本類型 --> <select id="findUserCount" resultType="int"> select count(*) from user </select> <select id="findUserByUserNameAndSex" parameterType="com.clj.pojo.User" resultType="com.clj.pojo.User"> select * from user <!-- where標籤做用: 會自動向sql語句中添加where關鍵字 會去掉第一個條件的and關鍵字 <where> <if test="username!=null and username !=''"> and username like '%${username}%' </if> <if test="sex !=null and sex!=''"> and sex=#{sex} </if> </where>--> <!-- 調用全局條件 --> <include refid="user_where"/> </select> <select id="findUserByIds" parameterType="com.clj.pojo.QueryVo" resultType="com.clj.pojo.User"> <!-- select * from user where id in (1,16,28,22) --> select * from user <where> <!-- 這裏的id指定是vo中的集合屬性 --> <if test="ids!=null"> <!-- foreach:循環傳入的集合參數 collection:傳入的集合的變量名稱 item:每次循環將循環的數據放入這個變量中 open:循環開始拼接的字符串 close:循環結束拼接的字符串 separator:循環中拼接的分隔符 --> <foreach collection="ids" item="id" open="id in (" close=")" separator=","> #{id} </foreach> </if> </where> </select> <!-- 關於一對一查詢 --> <!-- 方式一:自動映射 :利用類中的屬性對應表中的字段 須要提供封裝user和order屬性的類--> <select id="findOrderAndUser1" resultType="com.clj.pojo.CustomerOrders"> select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id=b.id </select> <!-- 一對以:手動映射:須要在order類中封裝User這個屬性 --> <!-- id:resultMap的惟一標識 type:將查詢出的數據放入指定的對象中 注意:手動映射須要指定數據表中的字段名與java中pojo類中的屬性名稱對應的關係 --> <resultMap type="com.clj.pojo.Orders" id="orderAndUserResultMap"> <!--id標籤指定主鍵字段對應關係 column:列,數據庫中的字段名稱 property:屬性,java中pojo中的屬性名稱 --> <id column="id" property="id"/> <!-- result:指定 非主鍵對應的關係--> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 這個標籤指定單個對象的對應關係 property:指定將數據放入Orders中的user屬性中 javaType:user屬性中類型的路徑 --> <association property="user" javaType="com.clj.pojo.User"> <id column="uid" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> </association> </resultMap> <select id="findOrderAndUser2" resultMap="orderAndUserResultMap"> select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id=b.id </select> <!-- 一對多 --> <resultMap type="com.clj.pojo.User" id="userAndOrderMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> <!-- 指定對應的集合對象關係映射 property:將數據放入User對象中的orderList屬性中 ofType:指定orderList屬性泛型類型 --> <collection property="ordersList" ofType="com.clj.pojo.Orders"> <id column="oid" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 注意:這裏不須要配置user屬性,他是用於一對一時配置的屬性,與這裏無關 --> </collection> </resultMap> <select id="findUserAndOrders" resultMap="userAndOrderMap"> select a.*,b.id oid,user_id,number,createtime from user a,order b where a.id=b.user_id </select> </mapper>
3))在applicationContext.xml映射文件中注入mapper接口
方式一:手動配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 加載配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 數據庫鏈接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> <!-- 整合後會話工廠歸spring來管理 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 指定mybatis核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml"></property> <!-- 指定會話工廠使用的數據源 --> <property name="dataSource" ref="dataSource"/> </bean> <!--配置原生Dao實現 --> <bean id="userDao" class="com.clj.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <!-- 動態代理方式:Mappper接口代理實現--> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 配置Mapper接口的全路徑名稱,其中property name="mapperInterface"是根據主類來配置的 <property name="mapperInterface" value="com.clj.UserMapper.UserMapper"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { private Class<T> mapperInterface; }
其中MapperScannerConfigurer的路徑爲
方式二:採用包掃描的方式
<!--使用包掃描的方式批量引入Mapper 掃描後引用時可使用類名,首字母小寫 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 指定要掃描的包的全路徑名稱 ,若是有多個,用逗號','隔開--> <!-- 此時能夠關掉SqlMapConfig.xml文件中對Mapper的掃描--> <property name="basePackage" value="com.clj.UserMapper"/> </bean>
其中MapperScannerConfigurer的路徑爲
若是採用包掃描的方式,他與mybatis中的sqlMapConfig.xml文件中掃描有衝突,須要屏蔽sqlMapConfig.xml的代碼
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://www.mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.clj.pojo"/> </typeAliases> <mappers> <mapper resource="User.xml"/> <!-- <package name="com.clj.UserMapper"/> --> </mappers> </configuration>
4))測試類
package com.clj.Test; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.clj.UserMapper.UserMapper; import com.clj.pojo.User; public class UserMapperTest { private ApplicationContext applicationContext; @Before public void setUp() throws Exception{ //這裏可加classpath,也可不加 String configLocation="classpath:applicationContext.xml"; applicationContext=new ClassPathXmlApplicationContext(configLocation); } @Test public void testFindUserById()throws Exception{
//方式一:手動配置:經過bean中id獲取 UserMapper userMapper=(UserMapper) applicationContext.getBean("userMapper");
//方式二:掃描方式:經過mapper接口名進行獲取,注意,getBean()中的值是經過類名第一個字母小寫獲得 User user=userMapper.findUserById(1); System.out.println(user); } }
自動生成Pojo類,還能夠自動生成Mapper接口和映射文件,注意:生成的方式是追加而不是覆蓋,因此不能夠重複生成,重複生成的文件有問題,若是想重複生成將原來生 成的文件刪除
1)下載核心jar包mybatis-generator-core-1.3.2
2)在項目工程(非src下)構建源碼包,用來存放配置文件
3)建立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
4)配置generatorConfig.xml文件
此文件用來配置Mapper中的信息(注意幾點:1. 添加要生成的數據庫表 2.pojo文件所在包路徑 3.mapper文件所在包路徑)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自動生成的註釋 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--數據庫鏈接的信息:驅動類、鏈接地址、用戶名、密碼 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.174.130:3306/SSM" userId="root" password="root"> </jdbcConnection> <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" userId="yycg" password="yycg"> </jdbcConnection> --> <!-- 默認false,把JDBC DECIMAL 和 NUMERIC 類型解析爲 Integer,爲 true時把JDBC DECIMAL 和 NUMERIC 類型解析爲java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO類的位置 --> <javaModelGenerator targetPackage="cn.clj.pojo" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> <!-- 從數據庫返回的值被清理先後的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="cn.clj.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.clj.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定數據庫表 --> <table tableName="orders"></table> <table tableName="user"></table> <!-- <table schema="" tableName="sys_user"></table> <table schema="" tableName="sys_role"></table> <table schema="" tableName="sys_permission"></table> <table schema="" tableName="sys_user_role"></table> <table schema="" tableName="sys_role_permission"></table> --> <!-- 有些表的字段須要指定java類型 <table schema="" tableName=""> <columnOverride column="" javaType="" /> </table> --> </context> </generatorConfiguration>
5)根據指定的路徑建立文件包
這裏要建立cn.clj.mapper與cn.clj.pojo包,逆向工程不會自動幫你鍵包,全部要提早建立
6)建立啓動類
注意:這裏的要配置generatorConfig.xml文件位置
package com.clj.Test; import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; public class StartService { public void generator() throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("config/generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { StartService startService = new StartService(); startService.generator(); } catch (Exception e) { e.printStackTrace(); } } }