視頻觀看地址: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對象
能使用#{}的地方都可以使用${}代替,但是能使用${}的地方不一定能夠用#{}來替代