上篇文章介紹了mybatis入門,在入門案例中使用了查詢所有操作,這篇文章介紹mybatis中對數據庫裏的CRUD操作,在這之前,先導入日誌分析工具log4j
目錄
一、日誌分析工具log4j
- 導入依賴jar包
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
-
添加配置文件
該配置文件只需要添加至resource文件夾下即可,log4j會自動讀取。文件名爲log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
- 結果
配置完成之後控制檯會出現很多的日誌信息
二、CRUD操作
注意:這裏只給出Dao接口類和對應的UserDaoConfig配置文件以及測試類的代碼,對於CRUD操作只需要修改這兩個地方
1. 查詢操作
- 查詢所有
com.Dao.userDao
/**
* 查詢所有
*/
List<User> findAll();
UserDaoConfig配置文件
<select id="findAll" resultType="com.Domain.User">
select * from user
</select>
爲避免測試類出現大量的重複代碼,使用如下簡化:
public class Test {
InputStream in;
SqlSessionFactoryBuilder builder;
SqlSessionFactory build;
SqlSession session;
UserDao userDao;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("MapperConfig.xml");
builder = new SqlSessionFactoryBuilder();
build = builder.build(in);
session = build.openSession();
userDao = session.getMapper(UserDao.class);
}
/**
* 測試查詢所有
* @throws IOException
*/
@org.junit.Test
public void testFindALll() throws IOException {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@After
public void destory() throws IOException {
//手動提交事務
session.commit();
in.close();
session.close();
}
}
- 根據id查詢
com.Dao.userDao
/**
* 根據id查詢
* @param userId
* @return
*/
User findById(Integer userId);
UserDaoConfig配置文件
<select id="findById" parameterType="int" resultType="com.Domain.User">
select * from user where id = #{id}
</select>
- select 標籤:書寫查詢sql語句
- id屬性:用於指定該sql語句對應那個方法
- parameterType:用於指定傳入參數的類型,這裏處基本數據類型外,其他類要寫全限定類
- resultType:用於指定結果集的類型。
- #{}:表示佔位符,與jdbc中的?作用類似
測試代碼
@org.junit.Test
public void testFindById(){
User user = userDao.findById(42);
System.out.println(user);
}
2.保存操作
- 新增用戶
com.Dao.userDao
/**
* 新增用戶
* @param user
*/
void saveUser(User user);
UserDaoConfig配置文件
<!-- 增 -->
<insert id="saveUser" parameterType="com.Domain.User" >
insert into user (username,birthday,sex,address) values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
測試代碼
/**
* 保存用戶
*/
@org.junit.Test
public void testSaveUser(){
User user = new User();
user.setBirthday(new Date());
user.setSex("男");
user.setUsername("zhangsan");
user.setAddress("西安市");
System.out.println(user);
userDao.saveUser(user);
}
- insert:書寫insert插入sql語句
- 注意:這裏必須要手動提交事務,如果不提交事務,mybatis會自動回滾事務,那麼就不能保存。
session.commit();
注意:新增用戶的id返回值。因爲這裏的id是AUTO_INCREMENT是自增長的,如果要返回當前新增的用戶的id值,那麼就要在UserDaoConfig配置文件中insert標籤中加入
<!-- 增 -->
<insert id="saveUser" parameterType="com.Domain.User" >
<selectKey keyColumn="id" keyProperty="id" resultType="int" >
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
然後運行
3.刪除操作
com.Dao.userDao
/**
* 刪除用戶
* @param id
* @return int
*/
int deleteUser(int id);
UserDaoConfig配置文件
<!-- 刪除用戶 -->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
測試代碼
@org.junit.Test
public void testDeleteuser(){
int deleteuser = userDao.deleteUser(42);
System.out.println(deleteuser);
}
4.更新操作
com.Dao.userDao
/**
* 更新用戶
*/
int updateUser(User user);
UserDaoConfig配置文件
<!-- 更新用戶 -->
<update id="updateUser" parameterType="com.Domain.User" >
update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where id = #{id}
</update>
5.模糊查詢
- #{}的方式
com.Dao.userDao
/**
* 模糊查詢
* @return
*/
List<User> fingByName(String username);
UserDaoConfig配置文件
<!-- 模糊查詢 -->
<select id="fingByName" parameterType="String" resultType="com.Domain.User">
select * from user where username like #{username};
</select>
測試代碼
@org.junit.Test
public void testFindByName(){
List<User> users = userDao.fingByName("%王%");
for (User user : users)
System.out.println(user);
}
}
注意:在sql語句中模糊查詢時要加入%%,但是我們在配置文件內沒有加入,所以要在傳入參數的時候加入,不加入則沒法模糊查詢
- ${}的方式
UserDaoConfig配置文件
<select id="fingByName" parameterType="String" resultType="com.Domain.User">
select * from user where username like '%${value}%';
</select>
測試代碼裏就不用%%了,這中方法明顯是使用拼接字符串的方式。並且需要注意的是${}裏面的值只能寫value寫其他內容則會報錯
6.聚合函數
com.Dao.userDao
int findtotal();
UserDaoConfig配置文件
<select id="findtotal" resultType="int">
select count(id) from user;
</select>
測試代碼
@org.junit.Test
public void testFindTatal(){
int count = userDao.findtotal();
System.out.println(count);
}
三、#{}與${}
#{}表示一個佔位符號
通過#{}可以實現 preparedStatement 向佔位符中設置值,自動進行 java 類型和 jdbc 類型轉換,#{}可以有效防止 sql 注入。 #{}可以接收簡單類型值或 pojo 屬性值。 如果 parameterType 傳輸單個簡單類型值,#{}括號中可以是 value或其它名稱。
${}表示拼接 sql 串
通過${}可以將 parameterType 傳入的內容拼接在 sql 中且不進行 jdbc 類型轉換, {}括號中只能是 value。
不使用resultType的方式
前面講的CRUD的操作傳入的參數都是使用了resultType這個標籤來實現的,其實也可以不使用這個標籤,例如:
com.Dao.userDao
/**
* 不使用resultType的方式
*/
User findById2(@Param("id") int id);
UserDaoConfig配置文件
<select id="findById2" resultType="com.Domain.User">
select * from user where id = #{param1};
</select>
可以使用@Param的方式來實現
四、mybatis的sql配置文件
1.parameterType
parameterType在Dao的配置文件中充當傳入參數的作用,它的格式爲:
- 實體類:全限定類名(沒有設置別名的情況下)
- 基本數據類型和String類:包名,類名,直接寫類型名稱
基本數據類型和String類型,可以不用寫全限定類名的原因是,mybatis已經將基本數據類型和String類設置了別名,所以只需要使用別名就可以。當然,mybatis還支持自定義別名,設置方法如下:在主配置文件下,配置typeAliases標籤,這個後面說明。
2.resultType
resultType屬性可以指定結果集類型,支持的結果集類型和parameterType一樣,當然也有定義別名。需要注意的是如果結果集是實體類,那麼實體類的屬性要和數據庫中的表的列名要一致。
3.resultMap
使用resultType必須要求數據庫表中的列名和實體類的屬性值要一致,如果不一致則會封裝不到數據,當然在數據庫的層面上提供了一個解決辦法,就是在sql語句中設置別名,不過這個方法有點麻煩。對於每條sql語句都要設置別名。
mybatis爲我們提供了一個解決辦法(這裏還要注意:mysql在windows下是不區分大小寫的)。就是使用resultMap封裝結果集。
實體類的屬性(getter和setter方法去掉get(set)後將首字母小寫):
public class User {
private Integer userid;
private String userName;
private String userSex;
private Date userBirthday;
private String userAddress;
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userid=" + userid +
", userName='" + userName + '\'' +
", userSex='" + userSex + '\'' +
", userBirthday=" + userBirthday +
", userAddress='" + userAddress + '\'' +
'}';
}
}
現在查詢所有肯定是查詢不到的、
但是還是有部分數據被查詢到了,這是因爲mysql在windows下不區分大小寫的原因。接下來就是要配置dao配置文件
userDaoConfig.xml
<resultMap id="userMap" type="com.Domain.User">
<id column="id" property="userid"></id>
<result column="username" property="userName"></result>
<result column="sex" property="userSex"></result>
<result column="address" property="userAddress"></result>
<result column="birthday" property="userBirthday"></result>
</resultMap>
<!--配置查詢所有-->
<select id="findAll" resultMap="userMap">
select id, username, sex as usersex, birthday from user
</select>
- type屬性:指定實體類的全限定類名
- id屬性:唯一標識,在sql語句的標籤內使用
- id標籤:主鍵字段
- result標籤:非主鍵字段
- column屬性:數據庫列名
- property屬性:實體類屬性名稱
指定好resultMap的配置之後,要在sql語句標籤中使用resultMap屬性,值爲設置的id,這樣就可以解決數據庫列名和實體類屬性值不一樣的問題了。
4.sql標籤
使用sql標籤,可以將一些常用的sql語句封裝好,要用的時候直接引用即可
<sql id="default">
select * from user
</sql>
<!--配置查詢所有-->
<select id="findAll" resultType="com.Domain.User">
<include refid="default"></include>
</select>
五、主配置文件詳解
主配置文件中的常見標籤以及順序
configuration
properties(屬性)
--property
-settings(全局配置參數)
--setting
-typeAliases(類型別名)
--typeAliase
--package
-environments(環境集合屬性對象)
--environment(環境子屬性對象)
---transactionManager(事務管理)
---dataSource(數據源)
-mappers(映射器)
--mapper
--package
這裏需要特別注意的是這些個配置文件的順序,是不能顛倒的,xml的約束是很嚴格的。
1.properties
這個標籤主要是改造dataSource的,在沒使用這個標籤之前,我們是這樣配置的
<dataSource type="POOLED">
<!-- 配置連接數據庫的4個基本信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/user?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="213213"/>
</dataSource>
在這裏寫顯得比較冗餘,這裏可以使用一個properties標籤,將這些信息寫入配置文件,其中的resource屬性可以用來指定配置文件的路徑。
主配置文件MapperConfig.xml
<properties resource="db.properties"></properties>
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/user?characterEncoding=UTF-8
username=root
password=213213
配置好了properties標籤之後,在dataSource數據源中就可以直接通過${key},這裏的key指的是在配置文件內使用的key。
<!-- 配置數據源(連接池) -->
<dataSource type="POOLED">
<!-- 配置連接數據庫的4個基本信息 -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
需要注意的是,db.properties需要寫在類路徑下,當然這個maven工程就要在resource目錄下了。
properties的屬性:
- resource:用於指定 properties 配置文件的位置,要求配置文件必須在類路徑下
- url:指定資源的url,不常用
當然,如果不想重新建一個配置文件,也可以在properties標籤下有一個子標籤propertie,在子標籤中有2個屬性,name和value,這兩個屬性的用處很顯然,name就是key,對應着配置文件中key,value。
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/user?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="213213"/>
</properties>
2.typeAliases
這個標籤在前面已經提到過,這個標籤是用來設置別名的,在resulttype或者是resulyMap中要寫全限定類名,如果每個配置都要這麼書寫則會很麻煩,於是mybatis給我們提供了這麼一個標籤,去寫別名
- typeAlias :單個定義別名
- alias:別名名稱
- type:要設置別名的類
- package:批量別名定義,掃描整個包下的類,別名爲類名(首字母大寫或小寫都可以)
<typeAliases>
<typeAlias type="com.Domain.User" alias="user"></typeAlias>
<package name="com.Domain"/>
</typeAliases>
3.mappers
這個標籤是用來配置dao配置文件的映射標籤,其中有個子標籤mapper指定其resource屬性或者class屬性