[toc]html
文章內容圖片部分上傳失敗,歡迎閱讀,白嫖電子書。
聲明:參考來源互聯網,有任何爭議能夠留言。站在前人的肩上,咱們才能看的更遠。本教程純手打,致力於最實用教程,不須要什麼獎勵,只但願多多轉發支持。
歡迎來我公衆號,但願能夠結識你,也能夠催更,微信搜索:JavaPubjava有任何問題均可以來談談,等你哦!mysql
對mybatis有必定了解的,能夠直接跳過前面基礎引入部分。
![idea建立maven工程截圖]()
![idea建立maven工程截圖]()面試
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency>
create database mydatabase;
DROP TABLE IF EXISTS tb_user; CREATE TABLE tb_user ( id char(32) NOT NULL, user_name varchar(32) DEFAULT NULL, password varchar(32) DEFAULT NULL, name varchar(32) DEFAULT NULL, age int(10) DEFAULT NULL, sex int(2) DEFAULT NULL, birthday date DEFAULT NULL, created datetime DEFAULT NULL, updated datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘zpc’, ‘123456’, ‘小明’, ‘22’, ‘1’, ‘1990-09-02’, sysdate(), sysdate()); INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘hj’, ‘123456’, ‘靜靜’, ‘22’, ‘1’, ‘1993-09-05’, sysdate(), sysdate());
7步操做數據庫spring
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * @author Evan */ public class JDBCTest { public static void main(String[] args) throws Exception { Connection connection = null; PreparedStatement prepareStatement = null; ResultSet rs = null; try { // 1,加載驅動 Class.forName("com.mysql.jdbc.Driver"); // 2,獲取鏈接 String url = "jdbc:mysql://127.0.0.1:3306/mydatabase"; String user = "root"; String password = "123456"; connection = DriverManager.getConnection(url, user, password); // 3,獲取statement,preparedStatement String sql = "select * from tb_user where id=?"; prepareStatement = connection.prepareStatement(sql); // 4,設置參數 prepareStatement.setLong(1, 1l); // 5,執行查詢 rs = prepareStatement.executeQuery(); // 6,處理結果集 while (rs.next()) { System.out.println(rs.getString("userName")); System.out.println(rs.getString("name")); System.out.println(rs.getInt("age")); System.out.println(rs.getDate("birthday")); } } finally { // 7,關閉鏈接,釋放資源 if (rs != null) { rs.close(); } if (prepareStatement != null) { prepareStatement.close(); } if (connection != null) { connection.close(); } } } }
![介紹截圖]()sql
官方文檔 http://www.mybatis.org/mybati...
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- 根標籤 --> <configuration> <!--<properties>--> <!-- <property name="driver" value="com.mysql.jdbc.Driver"/>--> <!-- <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true"/>--> <!-- <property name="username" value="root"/>--> <!-- <property name="password" value="123456"/>--> <!--</properties>--> <!-- 環境,能夠配置多個,default:指定採用哪一個環境 --> <environments default="test"> <!-- id:惟一標識 --> <environment id="test"> <!-- 事務管理器,JDBC類型的事務管理器 --> <transactionManager type="JDBC" /> <!-- 數據源,池類型的數據源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> <environment id="development"> <!-- 事務管理器,JDBC類型的事務管理器 --> <transactionManager type="JDBC" /> <!-- 數據源,池類型的數據源 --> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <!-- 配置了properties,因此能夠直接引用 --> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> </configuration>
<?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:命名空間,隨便寫,通常保證命名空間惟一 --> <mapper namespace="MyMapper"> <!-- statement,內容:sql語句。id:惟一標識,隨便寫,在同一個命名空間下保持惟一 resultType:sql語句查詢結果集的封裝類型,tb_user即爲數據庫中的表名 --> <select id="selectUser" resultType="com.zpc.mybatis.User"> select * from tb_user where id = #{id} </select> </mapper>
加入MyMapper.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> <!-- 環境,能夠配置多個,default:指定採用哪一個環境 --> <environments default="test"> <!-- id:惟一標識 --> <environment id="test"> <!-- 事務管理器,JDBC類型的事務管理器 --> <transactionManager type="JDBC" /> <!-- 數據源,池類型的數據源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mydatabase" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="mappers/MyMapper.xml" /> </mappers> </configuration>
// 指定全局配置文件 String resource = "mybatis-config.xml"; // 讀取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 構建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 獲取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 操做CRUD,第一個參數:指定statement,規則:命名空間+「.」+statementId // 第二個參數:指定傳入sql的參數:這裏是用戶id User user = sqlSession.selectOne("MyMapper.selectUser", 1); System.out.println(user);
MyBatisTest.javaapache
import com.zpc.test.pojo.User; 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 java.io.InputStream; public class MybatisTest { public static void main(String[] args) throws Exception { // 指定全局配置文件 String resource = "mybatis-config.xml"; // 讀取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 構建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 獲取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 操做CRUD,第一個參數:指定statement,規則:命名空間+「.」+statementId // 第二個參數:指定傳入sql的參數:這裏是用戶id User user = sqlSession.selectOne("MyMapper.selectUser", 1); System.out.println(user); } finally { sqlSession.close(); } } }
User.java緩存
import java.text.SimpleDateFormat; import java.util.Date; public class User { private String id; private String userName; private String password; private String name; private Integer age; private Integer sex; private Date birthday; private String created; private String updated; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getCreated() { return created; } public void setCreated(String created) { this.created = created; } public String getUpdated() { return updated; } public void setUpdated(String updated) { this.updated = updated; } }
1)配置mybatis-config.xml 全局的配置文件 (一、數據源,二、外部的mapper)2)建立SqlSessionFactory微信
3)經過SqlSessionFactory建立SqlSession對象
4)經過SqlSession操做數據庫 CRUD
5)調用session.commit()提交事務
6)調用session.close()關閉會話
import com.zpc.mybatis.pojo.User; import java.util.List; public interface UserDao { /** * 根據id查詢用戶信息 * * @param id * @return */ public User queryUserById(String id); /** * 查詢全部用戶信息 * * @return */ public List<User> queryUserAll(); /** * 新增用戶 * * @param user */ public void insertUser(User user); /** * 更新用戶信息 * * @param user */ public void updateUser(User user); /** * 根據id刪除用戶信息 * * @param id */ public void deleteUser(String id); }
import com.zpc.mybatis.dao.UserDao; import com.zpc.mybatis.pojo.User; import org.apache.ibatis.session.SqlSession; import java.util.List; public class UserDaoImpl implements UserDao { public SqlSession sqlSession; public UserDaoImpl(SqlSession sqlSession) { this.sqlSession = sqlSession; } @Override public User queryUserById(String id) { return this.sqlSession.selectOne("UserDao.queryUserById", id); } @Override public List<User> queryUserAll() { return this.sqlSession.selectList("UserDao.queryUserAll"); } @Override public void insertUser(User user) { this.sqlSession.insert("UserDao.insertUser", user); } @Override public void updateUser(User user) { this.sqlSession.update("UserDao.updateUser", user); } @Override public void deleteUser(String id) { this.sqlSession.delete("UserDao.deleteUser", id); } }
<?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:命名空間,隨便寫,通常保證命名空間惟一 --> <mapper namespace="UserDao"> <!-- statement,內容:sql語句。id:惟一標識,隨便寫,在同一個命名空間下保持惟一 resultType:sql語句查詢結果集的封裝類型,tb_user即爲數據庫中的表 --> <!--<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">--> <!--select * from tb_user where id = #{id}--> <!--</select>--> <!--使用別名--> <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select tuser.id as id, tuser.user_name as userName, tuser.password as password, tuser.name as name, tuser.age as age, tuser.birthday as birthday, tuser.sex as sex, tuser.created as created, tuser.updated as updated from tb_user tuser where tuser.id = #{id}; </select> <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user; </select> <!--插入數據--> <insert id="insertUser" parameterType="com.zpc.mybatis.pojo.User"> INSERT INTO tb_user ( user_name, password, name, age, sex, birthday, created, updated ) VALUES ( #{userName}, #{password}, #{name}, #{age}, #{sex}, #{birthday}, now(), now() ); </insert> <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update> <delete id="deleteUser"> delete from tb_user where id=#{id} </delete> </mapper>
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> </mappers>
pom.xml文件添加junit依賴
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
UserDao.java,按住Alt+Enter,選擇create test
import com.zpc.mybatis.dao.UserDao; import com.zpc.mybatis.dao.impl.UserDaoImpl; import com.zpc.mybatis.pojo.User; 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 java.io.InputStream; import java.util.Date; import java.util.List; public class UserDaoTest { public UserDao userDao; public SqlSession sqlSession; @Before public void setUp() throws Exception { // mybatis-config.xml String resource = "mybatis-config.xml"; // 讀取配置文件 InputStream is = Resources.getResourceAsStream(resource); // 構建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); // 獲取sqlSession sqlSession = sqlSessionFactory.openSession(); this.userDao = new UserDaoImpl(sqlSession); } @Test public void queryUserById() throws Exception { System.out.println(this.userDao.queryUserById("1")); } @Test public void queryUserAll() throws Exception { List<User> userList = this.userDao.queryUserAll(); for (User user : userList) { System.out.println(user); } } @Test public void insertUser() throws Exception { User user = new User(); user.setAge(16); user.setBirthday(new Date("1990/09/02")); user.setName("大鵬"); user.setPassword("123456"); user.setSex(1); user.setUserName("evan"); this.userDao.insertUser(user); this.sqlSession.commit(); } @Test public void updateUser() throws Exception { User user = new User(); user.setBirthday(new Date()); user.setName("靜鵬"); user.setPassword("654321"); user.setSex(1); user.setUserName("evanjin"); user.setId("1"); this.userDao.updateUser(user); this.sqlSession.commit(); } @Test public void deleteUser() throws Exception { this.userDao.deleteUser("4"); this.sqlSession.commit(); } }
查詢數據的時候,發現查不到userName的信息,
User{id=‘2’, userName=‘null’, password=‘123456’, name=‘靜靜’, age=22, sex=0, birthday=‘1993-09-05’, created=‘2018-06-30 18:22:28.0’, updated=‘2018-06-30 18:22:28.0’}
緣由:數據庫的字段名是user_name,POJO中的屬性名字是userName
兩端不一致,形成mybatis沒法填充對應的字段信息。修改方法:在sql語句中使用別名。
<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select tuser.id as id, tuser.user_name as userName, tuser.password as password, tuser.name as name, tuser.age as age, tuser.birthday as birthday, tuser.sex as sex, tuser.created as created, tuser.updated as updated from tb_user tuser where tuser.id = #{id}; </select>
org.apache.ibatis.binding.BindingException: Type interface com.zpc.mybatis.dao.UserDao is not known to the MapperRegistry. at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47) at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:655) at org.apache.ibatis.session.defaults.DefaultSqlSession.getMapper(DefaultSqlSession.java:222) at com.zpc.mybatis.test.UserDaoTest.setUp(UserDaoTest.java:32)
mapper.xml namespace
若是但願使用mybatis經過的動態代理的接口,就須要namespace中的值,和須要對應的Mapper(dao)接口的全路徑一致。Mapper中Namespace的定義自己是沒有限制的,只要不重複便可,但若是使用Mybatis的DAO接口動態代理,則namespace必須爲DAO接口的全路徑,例如:com.zpc.mybatis.dao.UserDao
<mapper namespace="com.zpc.mybatis.dao.UserDao">
public interface UserMapper { /** * 登陸(直接使用註解指定傳入參數名稱) * @param userName * @param password * @return */ public User login(@Param("userName") String userName, @Param("password") String password); /** * 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱) * @param tableName * @return */ public List<User> queryUserByTableName(@Param("tableName") String tableName); /** * 根據Id查詢用戶信息 * @param id * @return */ public User queryUserById(Long id); /** * 查詢全部用戶信息 * @return */ public List<User> queryUserAll(); /** * 新增用戶信息 * @param user */ public void insertUser(User user); /** * 根據id更新用戶信息 * @param user */ public void updateUser(User user); /** * 根據id刪除用戶信息 * @param id */ public void deleteUserById(Long id); }
<?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:命名空間,隨便寫,通常保證命名空間惟一 ,爲了使用接口動態代理,這裏必須是接口的全路徑名--> <mapper namespace="com.zpc.mybatis.dao.UserMapper"> <!-- 1.#{},預編譯的方式preparedstatement,使用佔位符替換,防止sql注入,一個參數的時候,任意參數名能夠接收 2.${},普通的Statement,字符串直接拼接,不能夠防止sql注入,一個參數的時候,必須使用${value}接收參數 --> <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select> <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select> <!-- statement,內容:sql語句。 id:惟一標識,隨便寫,在同一個命名空間下保持惟一,使用動態代理以後要求和方法名保持一致 resultType:sql語句查詢結果集的封裝類型,使用動態代理以後和方法的返回類型一致;resultMap:二選一 parameterType:參數的類型,使用動態代理以後和方法的參數類型一致 --> <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where id = #{id} </select> <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user </select> <!-- 新增的Statement id:惟一標識,隨便寫,在同一個命名空間下保持惟一,使用動態代理以後要求和方法名保持一致 parameterType:參數的類型,使用動態代理以後和方法的參數類型一致 useGeneratedKeys:開啓主鍵回寫 keyColumn:指定數據庫的主鍵 keyProperty:主鍵對應的pojo屬性名 --> <insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id" parameterType="com.zpc.mybatis.pojo.User"> INSERT INTO tb_user ( id, user_name, password, name, age, sex, birthday, created, updated ) VALUES ( null, #{userName}, #{password}, #{name}, #{age}, #{sex}, #{birthday}, NOW(), NOW() ); </insert> <!-- 更新的statement id:惟一標識,隨便寫,在同一個命名空間下保持惟一,使用動態代理以後要求和方法名保持一致 parameterType:參數的類型,使用動態代理以後和方法的參數類型一致 --> <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update> <!-- 刪除的statement id:惟一標識,隨便寫,在同一個命名空間下保持惟一,使用動態代理以後要求和方法名保持一致 parameterType:參數的類型,使用動態代理以後和方法的參數類型一致 --> <delete id="deleteUserById" parameterType="java.lang.String"> delete from tb_user where id=#{id} </delete> </mapper>
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> <mapper resource="mappers/UserMapper.xml"/> </mappers>
import com.zpc.mybatis.dao.UserMapper; import com.zpc.mybatis.pojo.User; 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 java.io.InputStream; import java.util.Date; import java.util.List; public class UserMapperTest { public UserMapper userMapper; @Before public void setUp() throws Exception { // 指定配置文件 String resource = "mybatis-config.xml"; // 讀取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 構建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 獲取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(true); // 1. 映射文件的命名空間(namespace)必須是mapper接口的全路徑 // 2. 映射文件的statement的id必須和mapper接口的方法名保持一致 // 3. Statement的resultType必須和mapper接口方法的返回類型一致 // 4. statement的parameterType必須和mapper接口方法的參數類型一致(不必定) this.userMapper = sqlSession.getMapper(UserMapper.class); } @Test public void testQueryUserByTableName() { List<User> userList = this.userMapper.queryUserByTableName("tb_user"); for (User user : userList) { System.out.println(user); } } @Test public void testLogin() { System.out.println(this.userMapper.login("hj", "123456")); } @Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); } @Test public void testQueryUserAll() { List<User> userList = this.userMapper.queryUserAll(); for (User user : userList) { System.out.println(user); } } @Test public void testInsertUser() { User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("大神"); user.setPassword("123456"); user.setSex(2); user.setUserName("bigGod222"); this.userMapper.insertUser(user); System.out.println(user.getId()); } @Test public void testUpdateUser() { User user = new User(); user.setBirthday(new Date()); user.setName("靜靜"); user.setPassword("123456"); user.setSex(0); user.setUserName("Jinjin"); user.setId("1"); this.userMapper.updateUser(user); } @Test public void testDeleteUserById() { this.userMapper.deleteUserById("1"); } }
使用mapper接口不用寫接口實現類便可完成數據庫操做,使用很是方便,也是官方推薦的使用方式。
- Mapper的namespace必須和mapper接口的全路徑一致。
- Mapper接口的方法名必須和sql定義的id一致。
- Mapper接口中方法的輸入參數類型必須和sql定義的parameterType一致。(這句須要再琢磨)
- Mapper接口中方法的輸出參數類型必須和sql定義的resultType一致。
mybatis-config.xml講究嚴格的順序,具體順序遵循文檔的順序。
properties配置的屬性都是可外部配置且可動態替換的,既能夠在典型的 Java 屬性文件中配置,亦可經過 properties 元素的子元素來傳遞。例如:
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
而後其中的屬性就能夠在整個配置文件中被用來替換須要動態配置的屬性值。好比:
<dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>
這個例子中的 username 和 password 將會由 properties 元素中設置的相應值來替換。 driver 和 url 屬性將會由 config.properties 文件中對應的值來替換。這樣就爲配置提供了諸多靈活選擇。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props); // ... or ... SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
若是屬性在不僅一個地方進行了配置,那麼 MyBatis 將按照下面的順序來加載:
- 在 properties 元素體內指定的屬性首先被讀取。
- 而後根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,並覆蓋已讀取的同名屬性。
- 最後讀取做爲方法參數傳遞的屬性,並覆蓋已讀取的同名屬性。
所以,經過方法參數傳遞的屬性具備最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
類型別名是爲 Java 類型命名的一個短的名字。它只和 XML 配置有關,存在的意義僅在於用來減小類徹底限定名的冗餘。
<typeAliases> <typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/> </typeAliases>
缺點:每一個pojo類都要去配置。
解決方案:使用掃描包,掃描指定包下的全部類,掃描以後的別名就是類名(不區分大小寫),建議使用的時候和類名一致
<typeAliases> <!--type:實體類的全路徑。alias:別名,一般首字母大寫--> <!--<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>--> <package name="com.zpc.mybatis.pojo"/> </typeAliases>
Mybatis已經爲普通的 Java 類型內建了許多相應的類型別名。它們都是大小寫不敏感的。
不管是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,仍是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。能夠重寫類型處理器或建立你本身的類型處理器來處理不支持的或非標準的類型。
MyBatis 容許你在已映射語句執行過程當中的某一點進行攔截調用。默認狀況下,MyBatis 容許使用插件來攔截的方法調用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
如今一些MyBatis 插件好比PageHelper都是基於這個原理,有時爲了監控sql執行效率,也可使用插件機制
原理:
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
配置:
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
上面的插件將會攔截在 Executor 實例中全部的 「update」 方法調用, 這裏的 Executor 是負責執行低層映射語句的內部對象。
MyBatis 能夠配置成適應多種環境,例如,開發、測試和生產環境須要有不一樣的配置;
儘管能夠配置多個環境,每一個 SqlSessionFactory 實例只能選擇其一。
雖然,這種方式也能夠作到很方便的分離多個環境,可是實際使用場景下,咱們更多的是選擇使用spring來管理數據源,來作到環境的分離。
須要告訴 MyBatis 到哪裏去找到 SQL 映射語句。即告訴 MyBatis 到哪裏去找映射文件。你可使用相對於類路徑的資源引用, 或徹底限定資源定位符(包括 file:/// 的 URL),或類名和包名等。例如:
<!-- 使用相對於類路徑的資源引用 --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers> <!-- 使用映射器接口實現類的徹底限定類名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
這裏所謂的mapper接口路徑。實際上就是dao的接口路徑。在mybatis中,一般把dao的包叫作mapper。類名,也叫作mapper
- 定義一個接口。
- 在接口所在的包中定義mapper.xml,而且要求xml文件和interface的名稱要相同。
- 在mybatis-config.xml 中經過class路徑,引入mapper(註解方式)。要求mapper.xml 中的名稱空間是類的接口的全路徑。
註解方式:
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> <!--註解方式可使用以下配置方式--> <mapper class="com.zpc.mybatis.dao.UserMapper"/> </mappers>
問題:
固然也可使用包掃描(必須使用註解方式,即在接口方法上使用註解,如@Select("select * from tb_user ")):
缺點:
select – 書寫查詢sql語句
select中的幾個屬性說明:
id屬性:當前名稱空間下的statement的惟一標識。必須。要求id和mapper接口中的方法的名字一致。
resultType:將結果集映射爲java的對象類型。必須(和 resultMap 二選一)
parameterType:傳入參數類型。能夠省略
insert 的幾個屬性說明:
id:惟一標識,隨便寫,在同一個命名空間下保持惟一,使用動態代理以後要求和方法名保持一致
parameterType:參數的類型,使用動態代理以後和方法的參數類型一致
useGeneratedKeys:開啓主鍵回寫
keyColumn:指定數據庫的主鍵
keyProperty:主鍵對應的pojo屬性名
標籤內部:具體的sql語句。
id屬性:當前名稱空間下的statement的惟一標識(必須屬性);
parameterType:傳入的參數類型,能夠省略。
標籤內部:具體的sql語句。
delete 的幾個屬性說明:
id屬性:當前名稱空間下的statement的惟一標識(必須屬性);
parameterType:傳入的參數類型,能夠省略。
標籤內部:具體的sql語句。
場景:數據庫有兩個如出一轍的表。歷史表,當前表
查詢表中的信息,有時候從歷史表中去查詢數據,有時候須要去新的表去查詢數據。
但願使用1個方法來完成操做。
<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from #{tableName} </select> /** * 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱) * * @param tableName * @return */ public List<User> queryUserByTableName(String tableName);
測試輸出:
有問題,報語法錯誤:至關於執行了這樣一條sql:
select * from 「tb_user」;
顯然表名多了引號。
<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select>
注意:
${} 是進行字符串拼接,至關於sql語句中的Statement,使用字符串去拼接sql;$能夠是sql中的任一部分傳入到Statement中,不能防止sql注入。
使用${} 去取出參數值信息,須要使用${value}
推薦:
/** * 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱) * * @param tableName * @return */ public List<User> queryUserByTableName(@Param("tableName") String tableName); <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select>
/** * 登陸(直接使用註解指定傳入參數名稱) * * @param userName * @param password * @return */ public User login( String userName, String password); <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select>
報錯:
org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2] ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]
解決方案一:
<select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{0} and password = #{1} </select>
解決方案二:
<select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{param1} and password = #{param2} </select>
最終解決方案:
/** * 登陸(直接使用註解指定傳入參數名稱) * * @param userName * @param password * @return */ public User login(@Param("userName") String userName, @Param("password") String password); <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select>
一般在方法的參數列表上加上一個註釋@Param(「xxxx」) 顯式指定參數的名字,而後經過${「xxxx」}或#{「xxxx」}
sql語句動態生成的時候,使用${};
sql語句中某個參數進行佔位的時候#{}
/** * #號 * @param username1 * @return */ User queryUserListByName1(@Param("username1") String username1); /** * $號 * @param username2 * @return */ User queryUserListByName2(@Param("username2") String username2); <select id="queryUserListByName1" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE user_name=#{username1} </select> <select id="queryUserListByName2" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE user_name='${username2}'//手動加了引號 </select>
使用:
<sql id=」」></sql> <include refId=」」 />
例如在UserMapper.xml中定義以下片斷:
<sql id="commonSql"> id, user_name, password, name, age, sex, birthday, created, updated </sql>
則能夠在UserMapper.xml中使用它:
<select id="queryUserById" resultMap="userResultMap"> select <include refid="commonSql"></include> from tb_user where id = #{id} </select> <select id="queryUsersLikeUserName" resultType="User"> select <include refid="commonSql"></include> from tb_user where user_name like "%"#{userName}"%" </select>
Sql片斷也能夠定義在單獨的.xml文件中如:
定義CommonSQL.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="CommonSQL"> <sql id="commonSql"> id, user_name, password, name, age, sex, birthday, created, updated </sql> </mapper>
使用:
<select id="queryUserById" resultMap="userResultMap"> select <include refid="CommonSQL.commonSql"></include> from tb_user where id = #{id} </select> <select id="queryUsersLikeUserName" resultType="User"> select <include refid="CommonSQL.commonSql"></include> from tb_user where user_name like "%"#{userName}"%" </select>
固然要完成這個功能還須要在全局配置文件mybatis-config.xml中引入該外部配置文件:
<mappers> <mapper resource="CommonSQL.xml"/> <!-- 開啓mapper接口的包掃描,基於class的配置方式 --> <package name="com.zpc.mybatis.mapper"/> </mappers>
場景:查詢男性用戶,若是輸入了姓名,按姓名模糊查詢
場景:查詢男性用戶,若是輸入了姓名,則按姓名查詢
定義接口:
/** * 查詢男性用戶,若是輸入了姓名,則按姓名查詢 * @param name * @return */ List<User> queryUserList(@Param("name") String name);
編寫mapper
<select id="queryUserList" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE sex=1 <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> </select>
測試:
@Test public void testqueryUserList() { List<User> users = this.userMapper.queryUserList(null); for (User user : users) { System.out.println(user); } }
場景:查詢男性用戶,若是輸入了姓名則按照姓名模糊查找,不然若是輸入了年齡則按照年齡查找,不然查找姓名爲「鵬程」的用戶。
定義接口:
/** * 查詢男性用戶,若是輸入了姓名則按照姓名模糊查找,不然若是輸入了年齡則按照年齡查找,不然查找姓名爲「鵬程」的用戶。 * @param name * @param age * @return */ List<User> queryUserListByNameOrAge(@Param("name") String name,@Param("age") Integer age);
編寫mapper配置:
<select id="queryUserListByNameOrAge" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE sex=1 <!-- 1.一旦有條件成立的when,後續的when則不會執行 2.當全部的when都不執行時,纔會執行otherwise --> <choose> <when test="name!=null and name.trim()!=''"> and name like '%${name}%' </when> <when test="age!=null"> and age = #{age} </when> <otherwise> and name='鵬程' </otherwise> </choose> </select>
測試:
@Test public void queryUserListByNameOrAge() throws Exception { List<User> users = this.userMapper.queryUserListByNameOrAge(null, 16); for (User user : users) { System.out.println(user); } }
場景一:查詢全部用戶,若是輸入了姓名按照姓名進行模糊查詢,若是輸入年齡,按照年齡進行查詢,若是二者都輸入,兩個條件都要成立。
接口:
/** * 查詢全部用戶,若是輸入了姓名按照姓名進行模糊查詢,若是輸入年齡,按照年齡進行查詢,若是二者都輸入,兩個條件都要成立 * @param name * @param age * @return */ List<User> queryUserListByNameAndAge(@Param("name") String name,@Param("age") Integer age);
配置:
<select id="queryUserListByNameAndAge" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user <!--若是多出一個and,會自動去除,若是缺乏and或者多出多個and則會報錯--> <where> <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> <if test="age!=null"> and age = #{age} </if> </where> </select>
測試:
@Test public void queryUserListByNameAndAge() throws Exception { List<User> users = this.userMapper.queryUserListByNameAndAge("鵬程", 20); for (User user : users) { System.out.println(user); } }
場景二:修改用戶信息,若是參數user中的某個屬性爲null,則不修改。
接口:
/** * 根據id更新用戶信息 * * @param user */ public void updateUser(User user);
配置:
<update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update>
測試:
@Test public void testUpdateUser() { User user = new User(); user.setBirthday(new Date()); user.setName("靜靜"); user.setPassword("123456"); user.setSex(0); user.setUserName("Jinjin"); user.setId("1"); this.userMapper.updateUser(user); }
場景:按照多個id查詢用戶信息
接口:
/** * 按多個Id查詢 * @param ids * @return */ List<User> queryUserListByIds(@Param("ids") String[] ids);
配置:
<select id="queryUserListByIds" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
測試:
@Test public void queryUserListByIds() throws Exception { List<User> users = this.userMapper.queryUserListByIds(new String[]{"1","2"}); for (User user : users) { System.out.println(user); } }
If:testognl表達式或者簡單java代碼
Choose when otherwise—>至關於if else if else
When test參考if
Where set 都有必定的糾錯功能
Trim:prefix suffix prefixOverrides suffixOverrides
Foreach:collection item saparator open close
在mybatis中,一級緩存默認是開啓的,而且一直沒法關閉
一級緩存知足條件:
一、同一個session中
二、相同的SQL和參數
測試:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); System.out.println(this.userMapper.queryUserById("1")); }
2018-07-01 17:08:50,156 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:08:50,421 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:08:50,423 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:08:50,476 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:08:50,509 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
使用:sqlSession.clearCache();能夠強制清除緩存
測試:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); sqlSession.clearCache(); System.out.println(this.userMapper.queryUserById("1")); }
日誌:
2018-07-01 17:10:51,065 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:10:51,359 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:10:51,360 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:10:51,408 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:10:51,437 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} 2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:10:51,440 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
執行update、insert、delete的時候,會清空緩存
測試:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); //sqlSession.clearCache(); User user=new User(); user.setName("美女"); user.setId("1"); userMapper.updateUser(user); System.out.println(this.userMapper.queryUserById("1")); }
日誌:
2018-07-01 17:18:15,128 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:18:15,399 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:18:15,401 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:18:15,466 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:18:15,492 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} 2018-07-01 17:18:15,527 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Preparing: UPDATE tb_user set name = ?, updated = now() WHERE (id = ?); 2018-07-01 17:18:15,529 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Parameters: 美女(String), 1(String) 2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] <== Updates: 1 2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:18:15,533 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:18:15,538 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
mybatis 的二級緩存的做用域是一個mapper的namespace ,同一個namespace中查詢sql能夠從緩存中命中。
開啓二級緩存:
<mapper namespace="com.zpc.mybatis.dao.UserMapper"> <cache/> </mapper>
測試:
@Test public void testCache() { System.out.println(this.userMapper.queryUserById("1")); sqlSession.close(); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.queryUserById("1")); }
開啓二級緩存,必須序列化:
public class User implements Serializable{ private static final long serialVersionUID = -3330851033429007657L;
日誌:
2018-07-01 17:23:39,335 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:23:39,664 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 2092769598. 2018-07-01 17:23:39,665 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:23:39,712 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:23:39,734 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'} 2018-07-01 17:23:39,743 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cbd213e] 2018-07-01 17:23:39,744 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 2092769598 to pool. 2018-07-01 17:23:39,746 [main] [com.zpc.mybatis.dao.UserMapper]-[DEBUG] Cache Hit Ratio [com.zpc.mybatis.dao.UserMapper]: 0.5 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
關閉二級緩存:
不開啓,或者在全局的mybatis-config.xml 中去關閉二級緩存
<settings> <!--開啓駝峯匹配--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--開啓二級緩存,全局總開關,這裏關閉,mapper中開啓了也沒用--> <setting name="cacheEnabled" value="false"/> </settings>
建立order表:
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) DEFAULT NULL,
order_number varchar(255) DEFAULT NULL,
create datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; }
需求說明:
方法一:核心思想擴展Order對象,來完成映射
新建OrderUser實體類繼承Order:
public class OrderUser extends Order { private String userName; private String password; private String name; private Integer age; private Integer sex; private Date birthday; private Date created; private Date updated; }
OrderMapper接口:
public interface OrderMapper { OrderUser queryOrderUserByOrderNumber(@Param("number") String number); }
配置OrderMapper:
<mapper namespace="com.zpc.mybatis.dao.OrderMapper"> <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser"> select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number} </select> </mapper>
測試:
@Test public void queryOrderUserByOrderNumber() throws Exception { OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001"); System.out.println(orderUser); }
方法二:面向對象的思想,在Order對象中添加User對象。
在Order對象中添加User屬性:
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; private User user; }
接口:
/** * 根據訂單號查詢訂單用戶的信息 * @param number * @return */ Order queryOrderWithUserByOrderNumber(@Param("number") String number);
使用resultType不能完成自動映射,須要手動完成結果集映射resultMap:
<resultMap id="OrderUserResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <!--association:完成子對象的映射--> <!--property:子對象在父對象中的屬性名--> <!--javaType:子對象的java類型--> <!--autoMapping:完成子對象的自動映射,若開啓駝峯,則按駝峯匹配--> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> </resultMap> <select id="queryOrderWithUserByOrderNumber" resultMap="OrderUserResultMap"> select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number} </select>
測試:
@Test public void queryOrderWithUserByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001"); System.out.println(order.getUser()); }
一對多查詢:查詢訂單,查詢出下單人信息而且查詢出訂單詳情。
Order類:
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; private User user; private List<OrderDetail> detailList; }
public class OrderDetail { private Integer id; private Integer orderId; private Double totalPrice; private Integer status; }
接口:
/** * 根據訂單號查詢訂單用戶的信息及訂單詳情 * @param number * @return */ Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);
Mapper映射:
<resultMap id="OrderUserDetailResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <!--collection:定義子對象集合映射--> <!--association:完成子對象的映射--> <!--property:子對象在父對象中的屬性名--> <!--javaType:子對象的java類型--> <!--autoMapping:完成子對象的自動映射,若開啓駝峯,則按駝峯匹配--> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true"> <id column="id" property="id"/> </collection> </resultMap> <select id="queryOrderWithUserAndDetailByOrderNumber" resultMap="OrderUserDetailResultMap"> select * from tb_order o left join tb_user u on o.user_id=u.id left join tb_orderdetail od on o.id=od.order_id where o.order_number = #{number} </select>
測試:
@Test public void queryOrderWithUserAndDetailByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001"); System.out.println(order.getUser()); System.out.println(order.getDetailList()); }
多對多查詢:查詢訂單,查詢出下單人信息而且查詢出訂單詳情中的商品數據。
OrderDetail類
public class OrderDetail { private Integer id; private Integer orderId; private Double totalPrice; private Integer status; private Item item; } public class Item { private Integer id; private String itemName; private Float itemPrice; private String itemDetail; }
接口:
/** * 根據訂單號查詢訂單用戶的信息及訂單詳情及訂單詳情對應的商品信息 * @param number * @return */ Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);
Mapper配置:
<resultMap id="OrderUserDetailItemResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true"> <id column="detail_id" property="id"/> <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true"> <id column="item_id" property="id"/> </association> </collection> </resultMap> <select id="queryOrderWithUserAndDetailItemByOrderNumber" resultMap="OrderUserDetailItemResultMap"> select * ,od.id as detail_id from tb_order o left join tb_user u on o.user_id=u.id left join tb_orderdetail od on o.id=od.order_id left join tb_item i on od.item_id=i.id where o.order_number = #{number} </select>
測試:
@Test public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001"); System.out.println(order); System.out.println(order.getUser()); System.out.println(order.getDetailList()); }
至此,目錄結構以下:
數據庫腳本: CREATE TABLE tb_order ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) DEFAULT NULL, order_number varchar(255) DEFAULT NULL, create datetime DEFAULT NULL, updated datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO tb_order VALUES (‘1’, ‘2’, ‘201807010001’, ‘2018-07-01 19:38:35’, ‘2018-07-01 19:38:40’); CREATE TABLE tb_item ( id int(11) NOT NULL, itemName varchar(255) DEFAULT NULL, itemPrice decimal(10,2) DEFAULT NULL, itemDetail varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO tb_item VALUES (‘1’, ‘襪子’, ‘29.90’, ‘香香的襪子’); INSERT INTO tb_item VALUES (‘2’, ‘套子’, ‘99.99’, ‘岡本001’); CREATE TABLE tb_orderdetail ( id int(11) NOT NULL AUTO_INCREMENT, order_id int(11) DEFAULT NULL, total_price decimal(10,0) DEFAULT NULL, item_id int(11) DEFAULT NULL, status int(10) unsigned zerofill DEFAULT NULL COMMENT ‘0成功非0失敗’, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO tb_orderdetail VALUES (‘1’, ‘1’, ‘10000’, ‘1’, ‘0000000001’); INSERT INTO tb_orderdetail VALUES (‘2’, ‘1’, ‘2000’, ‘2’, ‘0000000000’);
resutlType沒法幫助咱們自動的去完成映射,因此只有使用resultMap手動的進行映射。
type 結果集對應的數據類型 id 惟一標識,被引用的時候,進行指定。
<resultMap type="Order" id="orderUserLazyResultMap"> <!—定義pojo中的單個對象的 property 定義對象的屬性名, javaType 屬性的類型, <association property="user" javaType="User" autoMapping="true"> <id /> </association> <!—若是屬性是集合使用collection ,javaType 集合的類型,ofType 表示集中的存儲的元素類型 <collection property="details" javaType="List" ofType="OrderDetail" autoMapping="true"> <id /> </resultMap>
後續補充
由於業務,須要在mybatis中,使用到大於號,小於號,因此就在SQL中直接使用了。
但是,在執行時,總報錯誤:`Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 74; columnNumber: 17;
元素內容必須由格式正確的字符數據或標記組成。
把AND start_date >= CURRENT_DATE AND end_date <= CURRENT_DATE去掉,就沒有問題,因此肯定是由於大於號,小於號引發的問題。
因而就想到了特殊符號,因而用了轉義字符把>和<替換掉,而後就沒有問題了。
案例:
1.<if test="startDateTime!=null"> and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss')</if> 2.<if test="endDateTime!=null"> and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss')</if>
案例1:
<![CDATA[ and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss') and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss') ]]>
案例2:
mapper文件示例代碼 :
and (t1.status <![CDATA[ >= ]]> 1 and t1.status <![CDATA[ <= ]]> 2) 上述代碼其實對應的sql: and (t1.status > =1 andt1.status <= 2)
注意:
使用<![CDATA[ ]]>標記的sql語句中的<where> <if>等標籤不會被解析。CDATA 部分中的全部內容都會被解析器忽略。CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結束