使用ONGL表達式解析對象字段的值,#{}或者${}中的值爲POJO屬性的名稱 user.usernamejava
查詢條件是多個查詢條件的綜合mysql
1.3.1 QueryVospring
public class QueryVo { private User user; public User getUser() { returnuser; } publicvoid setUser(User user) { this.user = user; } }
1.3.2 UserMapper.xmlsql
<!-- 使用包裝類型查詢用戶 使用ognl從對象中取屬性值,若是是包裝對象可使用.操做符來取內容部的屬性 --> <select id="findUserByQueryVo" parameterType="com.guojie.pojo.QueryVo" resultType="user"> SELECT * FROM user where username like '%${user.username}%' and sex=#{user.sex} // 查詢條件爲多個時,入參類型須要爲POJO
parameterType
</select>
1.3.3 UserMapper接口中數據庫
public List<User> findUserByQueryVo(QueryVo vo);
1.3.4 測試apache
@Test public void testFindUserByQueryVo() throws Exception { SqlSession sqlSession = sessionFactory.openSession(); //得到mapper的代理對象,經過getMapper方法實例化接口 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建立QueryVo對象 QueryVo queryVo = new QueryVo(); //建立user對象 User user = new User(); user.setUsername("劉"); user.setSex("1"); queryVo.setUser(user);
//根據queryvo查詢用戶 List<User> list = userMapper.findUserByQueryVo(queryVo); System.out.println(list); sqlSession.close();
}
2.1.1 UserMapper.xml數組
<!-- 獲取用戶列表總數 --> <select id="findUserCount" resultType="int"> select count(*) from user </select>
2.1.2 UserMapper接口session
public int findUserCount() throws Exception;
2.1.3 測試mybatis
Public void testFindUserCount() throws Exception{ //獲取session SqlSession session = sqlSessionFactory.openSession(); //獲取mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); int count = userMapper.findUserCount(); //關閉session session.close(); }
resultType須要POJO屬性和sql查詢的列名一致才能將查詢結果映射爲POJO,自動映射oracle
resultMap在POJO屬性和sql查詢的列名不一致時也行,可用於映射覆雜類型的POJO,須要手動配置
<select id="selectOrderList" resultMap="orders"> select user_id, user_name from user </select>
<resultMap type="Orders" id="orders"> <result column="user_id" property="userId"> </resultMap>
id:結果集的惟一標識
property:POJO類的屬性
column:sql字段
經過MyBatis提供的各類標籤方法實現動態拼接sql
<select id="findUserByNameAndSex" parameterType="cn.guojie.pojo.User" resultType="cn.guojie.pojo.User"> <where> <if test="username!=null and username!=' ' "> and username like '%${username}%' </if> <if test="sex!=null and sex!=' ' "> and sex=#{sex} </if> <where> </select>
where做用:添加where關鍵字,去掉第一個條件的and關鍵字
條件中username爲POJO的屬性
提取重複的sql條件封裝重用
<sql id="userFileds"> 重複代碼 </sql>
<select> <!--調用sql條件 --> <include refid="userField" /> </select>
向sql傳數組或list
<select id="findUserByIds" parameterType="cn.guojie.pojo.QueryVo" resultType="com.guojie.pojo.User"> <where> <!-- ids爲QueryVo中的List集合屬性 --> <if test="ids"!=null> <foreach collection="ids" item="id" open="id in (" close=")「 seperator="," 」> #{id} </foreach> </if> </where> </select>
等同於select * from user whereid in (1, 2, 3)
collection:傳入的集合變量名
item:循環的數據存入變量
open:開始拼接的字符串
close:結束拼接的字符串
seperator:分隔符
sql中不要有or,會形成性能降低,用in
@Test public void testFindUserByIds() throws Execption { SqlSession openSession = factory.openSession(); // 經過getMapper方法實例化接口 UserMapper mapper = openSession.getMapper(UserMapper.class); QueryVo vo = new QueryVo(); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(3); vo.setIds(ids); List<User> list = mapper.findUserByIds(vo); }
多中有一的屬性引用,一中有多的集合引用
以訂單爲中心,單個訂單隻能屬於一個用戶,相對用戶一對一,訂單表以用戶表的id爲外鍵
互聯網通常單表查詢多,關聯查詢較少
根據表的字段名和POJO類中的屬性名對應
select a.*, b.id uid, username, birthday, sex, address
from orders a, user b
where a.userId = b.id
1.1.1 自定義OrdersCustom
包含用戶和訂單中全部屬性或者繼承Orders類,再加上User類的屬性
public class OrdersCustom extends Orders { private String username;// 用戶名稱 private String address;// 用戶地址 setter&getter; }
<!-- 查詢全部訂單信息 --> <select id="findOrdersList" resultType="cn.guojie.mybatis.pojo.OrdersCustom"> select a.*, b.id uid, username, birthday, sex, address from orders a, user b where a.user_id = b.id </select>
public void testfindOrdersList() throws Exception{ //獲取session SqlSession session = sqlSessionFactory.openSession(); //獲取mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); //查詢訂單信息 List<OrdersCustom> list = userMapper.findOrdersList(); System.out.println(list); //關閉session session.close(); }
指定表中字段名和POJO類中的屬性名的對應關係
用association完成關聯查詢
1.2.1 在Orders類中加入User對象
private User user;
1.2.2 OrderMapper.xml中
<!-- 查詢訂單關聯用戶信息使用resultmap --> <resultMap type="cn.guojie.pojo.Orders" id="orderUserResultMap"> <!-- id爲主鍵字段,column爲表字段,property爲POJO屬性,result爲非主鍵字段 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 一對一關聯映射 --> <!-- 爲Order中增長的user對象設置對應關係 property : Orders對象的user屬性 javaType:user屬性對應的類型 --> <association property="user" javaType="cn.guojie.pojo.User"> <!-- column:user表的主鍵對應的列 property:user對象中id屬性--> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> </resultMap>
<select id="findOrdersList" resultMap="orderUserResultMap"> select a.*, b.id uid, username, birthday, sex, address from orders a, user b where a.user_id = b.id </select>
1.2.3 OrderMapper接口中
public List<Orders> findOrdersList();
1.2.4 測試
public void testfindOrdersListResultMap() throws Exception{ //獲取session SqlSession session = sqlSessionFactory.openSession(); //獲取mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); //查詢訂單信息 List<Orders> list = userMapper.findOrdersList(); System.out.println(list); //關閉session session.close(); }
以用戶爲中心,一個用戶對應多個訂單
只能手動映射,在User類中加入Order的List<Orders>集合
private List<Orders> orderList;
<resultMap type="cn.guojie.pojo.user" id="userOrderResultMap"> <!-- 用戶信息映射 --> <id column="id property="id" "/> <result column="username property="username" "/> <result column="birthday property="birthday" "/> <result column="sex property="sex" "/> <result column="address property="address""/> <!-- 一對多關聯映射 集合對象關係映射 property:將數據放入User對象中的orderList屬性中 ofType:指定orderList屬性的泛型類型 --> <collection property="orders" ofType="cn.guojie.pojo.Orders"> <id column="oid property="id" "/> <!--用戶id已經在user對象中存在,此處能夠不設置--> <!-- <result column="id property="userId""/> --> <result column="number property="number" "/> <result column="createtime property="createtime" "/> <result column="note property="note""/> </collection> </resultMap>
<select id="finUserAndOrders" resultMap="userOrderResultMap"> select a.*, b.id oid, number,createtime from user a, order b where a.id = b.user_id </select>
public List<User> findUserAndOrders();
@Test public void testFindUserAndOrders() { SqlSession session = sqlSessionFactory.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); List<User>result = userMapper.getUserOrderList(); for (User user : result) { System.out.println(user); } session.close(); }
(1)數據庫鏈接池及其事務管理應交給Spring容器管理
(2)SqlSessionFactory工廠對象應該放到Spring容器中做爲單例對象
(3)傳統DAO開發中,應從Spring容器中得到sqlSession對象;Mapper動態代理形式中,應從Spring容器中得到mapper的接口代理對象
2.1 導包
Spring 、MyBatis、Spring+MyBatis整合包、MySQL數據庫驅動包、數據庫鏈接池DBCP(比C3P0效率低)
2.2 Spring核心配置文件applicationContext.xml
<?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> <!-- mapper配置 --> <!-- 讓spring管理sqlsessionfactory 使用mybatis和spring整合包中的 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 數據庫鏈接池 --> <property name="dataSource" ref="dataSource"/> <!-- 加載mybatis的全局配置文件 --> <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/> </bean> </beans>
Spring容器配置文件須要加classpath
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
MyBatis核心配置文件
<?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> <package name="cn.guojie.mybatis.pojo"/> </typeAliases> <mappers> <mapperresource="sqlmap/User.xml"/> </mappers> </configuration>
接口+實現類,實現類繼承自SqlSessionSupport類,提供getSqlSession()來獲取SqlSession
須要在Spring配置文件中指定DAO類
DAO實現類須要繼承SqlSessionDaoSupport超類
在DAO實現類中不要手動關閉會話,不要提交事務
applicationContext.xml中
<!-- 配置UserDao實現類 --> <bean id="userDao" class="cn.guojie.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
DAO實現類
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { @Override public User findUserById(int id) throws Exception { SqlSession session = this.getSqlSession(); User user = session.selectOne("test.findUserById", id); //不能關閉SqlSession,讓spring容器來完成 //session.close(); return user; } @Override public void insertUser(User user) throws Exception { SqlSession session = this.getSqlSession(); session.insert("test.insertUser", user); session.commit(); //session.close(); } }
測試
public class UserDaoTest { private ApplicationContext applicationContext; @Before public void setUp() throws Exception{ String configLocation = "classpath:spring/ApplicationContext.xml"; //初始化spring運行環境 applicationContext = new ClassPathXmlApplicationContext(configLocation); } @Test public void testFindUserById() throws Exception { UserDao userDao = (UserDao) applicationContext.getBean("userDao"); User user = userDao.findUserById(1); System.out.println(user); } }
只須要接口,由MyBatis生成其實現類
applicationContext.xml中
方式一
<!-- 配置mapper代理對象 --> <bean id=userMapper class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- 配置mapper接口全路徑名--> <property name="mapperInterface" value="cn.guojie.mybatis.mapper.UserMapper"/> <propertyname="sqlSessionFactory"ref="sqlSessionFactory"></property> </bean>
public class UserMapperTest { private ApplicationContext applicationContext; @Before publicvoid setUp() throws Exception { applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml"); } @Test public void testGetUserById() { UserMapper userMapper = applicationContext.getBean(UserMapper.class); User user = userMapper.getUserById(1); System.out.println(user); } }
<!-- 使用掃描包的形式來建立mapper代理對象 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.guojie.mybatis.mapper"></property> </bean>
每一個mapper代理對象的id就是類名,掃描後引用時首字母小寫
SqlMapConfig.xml中<package name="cn.guojie.mapper"/>包掃描批量引入接口能夠不要了,重複引用
MyBatis核心包
數據庫驅動
逆向工程包
日誌包log4j-1.2.16.jar
(1)POJO所在的包路徑注意修改
(2)添加要生成的數據庫表
(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://localhost:3306/mybatis" userId="root" password="admin"> </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:生成POJO類的位置 --> <javaModelGenerator targetPackage="cn.guojie.pojo" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> <!-- 從數據庫返回的值被清理先後的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置,和接口放在同一目錄 --> <sqlMapGenerator targetPackage="cn.guojie.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 和映射文件放在同一目錄 --> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.guojie.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema做爲包的後綴 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定數據庫表 --> <!-- <table tableName="items"></table> --> <table tableName="orders"></table> <!-- <table tableName="orderdetail"></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>
public class StartServer { public void generator() throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("genarator.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 { StartServer startServer = new StartServer(); startServer.generator(); } catch (Exception e) { e.printStackTrace(); } } }
生成文件的方式是追加而不是覆蓋,運行第二次會再生成一遍,要刪除原來的再生成,否則會報錯
mapper xml文件和mapper.java文件在一個目錄內且文件名相同
public class UserMapperTest { private ApplicationContext applicatonContext; @Before public void setUp() throws Exception{ String configLocation = "classpath:ApplicationContext.xml"; applicatonContext = new ClassPathXmlApplicationContext(configLocation); } @Test public void testFindUserById() throws Exception{ UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper"); User user = userMapper.selectByPrimaryKey(1); System.out.println(user); } @Test public void testFindUserAndSex() throws Exception{ UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper"); //建立UserExample對象 UserExample userExample = new UserExample(); //經過UserExample對象建立查詢條件封裝對象(Criteria中是封裝的查詢條件) Criteria createCriteria = userExample.createCriteria(); //加入查詢條件 createCriteria.andUsernameLike("%王%"); createCriteria.andSexEqualTo("1"); List<User> list = userMapper.selectByExample(userExample); System.out.println(list); } }
like模糊查詢時要加%
POJO:不按MVC分層,只有JavaBean的一些屬性和setter&getter
Domain:不按MVC分層,只有JavaBean的一些屬性和setter&getter
PO:用於持久層,在增長或者修改的時候,從頁面直接傳入action中,其中JavaBean類名等於表名,屬性名等於字段名,還有對應的setter&getter
VO:View Object表現層對象,主要用於在高級查詢中從頁面接收傳過來的各類條件參數,好處是擴展性強
BO:在Service,如今基本不用