MyBatis學習(四)

視頻觀看地址:http://edu.51cto.com/course/14674.html?source=so

1、Mapper.xml文件

1.1、insert、update、delete、select

<!-- 
    id:保證唯一
    resultMap和resultType只能2選其一
    parameterType:參數類型(基本數據類型、pojo、HashMap)
  -->
  <select id="selectUserById" parameterType="" resultMap="" resultType="User">
    select userid,user_name as userName,age,pwd,sex,birthday from tb_user where userid = #{userid}
  </select>

1.2、resultMap元素

先使用resultMap解決數據庫字段名和java屬性名不一致的問題

修改mapper.xml文件

<resultMap type="User" id="UserMap" autoMapping="true">
    <!-- id表示主鍵,必須設置 
         column:數據庫列名稱
         property:實體類中的屬性名
    -->
    <id column="userid" property="userid"/>
    <result column="user_name" property="userName"/>
  </resultMap>
  <select id = "selectAll" resultMap="UserMap">
    select * 
    from tb_user
  </select>

爲了測試完美,將駝峯命名關閉

<settings>
        <setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>

日誌文件

DEBUG - Opening JDBC Connection
DEBUG - Created connection 25899648.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@18b3280]
DEBUG - ==>  Preparing: select * from tb_user 
DEBUG - ==> Parameters: 
DEBUG - <==      Total: 5
User [userid=8, userName=阿珂, pwd=123456, age=18, sex=女, birthday=Mon Aug 13 14:06:14 CST 2018]
User [userid=2, userName=張三, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
User [userid=3, userName=李四, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
User [userid=4, userName=王五, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
User [userid=5, userName=趙六, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@18b3280]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@18b3280]
DEBUG - Returned connection 25899648 to pool.

總結一下:解決數據庫名和屬性名一致的解決方案:

1.別名

2.駝峯命名

3.resultMap

1.3、獲取自增長的id元素

修改mapper.xml文件

 <!-- 
        useGeneratedKeys:將生成的id返回給java對象
        keyColumn:主鍵列
        keyProperty:主鍵的屬性(業務屬性)
  -->
  <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyColumn="userid" keyProperty="userid">
    insert into tb_user(userid,user_name,age,pwd,sex,birthday)
    values(seq_user.nextval,#{userName},#{age},#{pwd},#{sex},#{birthday})
  </insert>

測試代碼中

@Test
    public void testInsertUser() {
        User vo = new User("阿珂3", "123456", 18, "女", new Date());
        try {
            userMapper.insertUser(vo);
            //提交事務
            sqlSession.commit();
            System.out.println(vo.getUserid());
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        }
    }

測試日誌

DEBUG - Opening JDBC Connection
DEBUG - Created connection 1434803926.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@55855ed6]
DEBUG - ==>  Preparing: insert into tb_user(userid,user_name,age,pwd,sex,birthday) values(seq_user.nextval,?,?,?,?,?) 
DEBUG - ==> Parameters: 阿珂3(String), 18(Integer), 123456(String), 女(String), 2018-08-13 14:57:50.296(Timestamp)
DEBUG - <==    Updates: 1
DEBUG - Committing JDBC Connection [oracle.jdbc.driver.T4CConnection@55855ed6]
10
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@55855ed6]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@55855ed6]
DEBUG - Returned connection 1434803926 to pool.

2、參數傳遞

2.1、#{}方式

當參數有多個的時候,我們可以採用自然數,或者pojo對象

方式一:採用自然數傳遞

需求:按照用戶的姓名和年齡進行查詢數據

1、添加一個方法

public List<User> queryByNameAndAge(String name,int age) throws Exception;

2、編寫mapper.xml文件

 <select id="queryByNameAndAge" resultMap="UserMap">
        select * from tb_user where user_name like #{0} and age =#{1}
  </select>

3、執行測試代碼

@Test
    public void testQueryByNameAndAge() throws Exception{
        List<User> list = userMapper.queryByNameAndAge("%阿%", 18);
        for (User user : list) {
            System.out.println(user);
        }
    }

日誌文件

DEBUG - Opening JDBC Connection
DEBUG - Created connection 707919597.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@2a31feed]
DEBUG - ==>  Preparing: select * from tb_user where user_name like ? and age =? 
DEBUG - ==> Parameters: %阿%(String), 18(Integer)
DEBUG - <==      Total: 3
User [userid=8, userName=阿珂, pwd=123456, age=18, sex=女, birthday=Mon Aug 13 14:06:14 CST 2018]
User [userid=9, userName=阿珂2, pwd=123456, age=18, sex=女, birthday=Mon Aug 13 14:56:45 CST 2018]
User [userid=10, userName=阿珂3, pwd=123456, age=18, sex=女, birthday=Mon Aug 13 14:57:50 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@2a31feed]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@2a31feed]
DEBUG - Returned connection 707919597 to pool.

實際上還可以同param傳遞,但是param在傳遞的時候從1開始

修改mapper.xml

 <select id="queryByNameAndAge" resultMap="UserMap">
        select * from tb_user where user_name like #{param1} and age =#{param2}
  </select>

但是以上方式實際上可讀性並不高,一般我們可以採用註解的形式:

方式二:採用註解的方式傳遞離散的參數

接口的聲明如下

public List<User> queryByNameAndAge(@Param("name")String name,@Param("age")int age) throws Exception;

mapper.xml文件就可以按如下方式編寫

 <select id="queryByNameAndAge" resultMap="UserMap">
        select * from tb_user where user_name like #{name} and age =#{age}
  </select>

方式三:直接傳遞一個pojo對象

1、首先創建一個查詢對象,這個對象中封裝了查詢需要的參數

package cn.org.kingdom.pojo;

import java.io.Serializable;

public class QueryUser implements Serializable {
    private String name ; 
    private int age ;

    public QueryUser() {
        super();
    }
    public QueryUser(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    } 

}

2、編寫接口方法

public List<User> queryByPojo(QueryUser  vo) throws Exception;

3、編寫mapper.xml文件

<select id = "queryByPojo" parameterType="QueryUser" resultMap="UserMap">
     select * from tb_user where user_name like #{name} and age =#{age}
  </select>

4、測試

@Test
    public void testQueryByNameAndAge2() throws Exception{
        QueryUser vo = new QueryUser("%阿%", 18);
        List<User> list = userMapper.queryByPojo(vo);
        for (User user : list) {
            System.out.println(user);
        }
    }

總結:一般情況下在開發中,會優先選擇註解和pojo的方式來進行開發,關於自然數的方式,大家瞭解即可

2.2、${}方式

需求:

數據庫有兩個一模一樣的表。歷史表,當前表

查詢表中的信息,有時候從歷史表中去查詢數據,有時候需要去新的表去查詢數據。

希望使用 1 個方法來完成操作

接口方法定義

public List<User> queryByTableName(@Param("tableName")String tableName) throws Exception;

mapper.xml文件定義

<select id= "queryByTableName" resultMap="UserMap">
    select * from #{tableName}
  </select>

測試類代碼

@Test
    public void testQuerybyTableName() throws Exception{
        List<User> list = userMapper.queryByTableName("tb_user_hi");
        for (User user : list) {
            System.out.println(user);
        }
    }

運行:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.sql.SQLException: ORA-00903: 表名無效

### The error may exist in cn/org/kingdom/mapper/UserMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select * from ?
### Cause: java.sql.SQLException: ORA-00903: 表名無效

    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:111)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:102)
    at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:119)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)
    at com.sun.proxy.$Proxy4.queryByTableName(Unknown Source)
    at cn.org.kingdom.test.MyBatisTest01.testQuerybyTableName(MyBatisTest01.java:120)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4Cla***unner.runChild(BlockJUnit4Cla***unner.java:70)
    at org.junit.runners.BlockJUnit4Cla***unner.runChild(BlockJUnit4Cla***unner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

發現有問題,實際上#{}方式通過?形式進行傳遞參數的,?它不支持tableName

將#{}換成${}

<select id= "queryByTableName" resultMap="UserMap">
    select * from ${tableName}
  </select>

再次運行

DEBUG - Opening JDBC Connection
DEBUG - Created connection 1891119713.
DEBUG - Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@70b83261]
DEBUG - ==>  Preparing: select * from tb_user_hi 
DEBUG - ==> Parameters: 
DEBUG - <==      Total: 2
User [userid=2, userName=張三, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
User [userid=3, userName=李四, pwd=123456, age=10, sex=男, birthday=Mon Aug 13 10:07:55 CST 2018]
DEBUG - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@70b83261]
DEBUG - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@70b83261]
DEBUG - Returned connection 1891119713 to pool.

總結:

#{} :表示sql中的參數部分,實際上底層使用的是PreparedStatement

${}:表示字符串拼接,實際上底層採用的Statement對象

能使用#{}的地方都可以使用${}代替,但是能使用${}的地方不一定能夠用#{}來替代

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章