MyBatis框架安排
目录
2. 第二天:
1. MyBatis的增删改查操作(操作配置文件SqlMapConfig.xml)
-
在SqlMapConfig.xml中向数据库中增加条目
<!-- 插入数据 --> <!-- parameterType="com.liuzeyu.domin.User"参数类型,通过反射为#{username}...赋值--> <insert id="save" parameterType="com.liuzeyu.domin.User"> <!-- 插入数后返回id,keyProperty="id"对应实体类属性,keyColumn="id"对应数据库列名,AFTER:操作最后执行--> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> <!-- SELECT last_insert_id() 返回刚刚插入的数据id-- > SELECT last_insert_id() </selectKey> insert into user (username,birthday,sex,address)VALUES (#{username},#{birthday},#{sex},#{address}) </insert>
-
在SqlMapConfig.xml中向数据库中删除条目
<!-- 根据id删除--> <delete id="delete" parameterType="int"> delete from user where id=#{uid} </delete>
-
在SqlMapConfig.xml向数据库中修改条目
<!-- 更新数据 --> <update id="update" parameterType="com.liuzeyu.domin.User"> UPDATE user SET username=#{username},birthday=#{birthday},address=#{address},sex=#{sex} where id=#{id} </update>
-
在SqlMapConfig.xml向数据库中查询条目
<!-- 根据id查找一个 --> <select id="findById" resultType="com.liuzeyu.domin.User" parameterType="int"> select * from user where id=#{uid} </select> <!-- 根据name查找集合 --> <select id="findByName" resultType="com.liuzeyu.domin.User" parameterType="string"> select * from user where username like #{string} <!-- select * from user where username like '%${value}%' --> </select> <!-- 查询总记录数--> <select id="findTotal" resultType="int"> SELECT count(*) FROM USER </select>
测试类:
```
package com.liuzeyu.test;
import com.liuzeyu.dao.IUserDao;
import com.liuzeyu.domin.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.After;
import org.junit.Before;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class Test {
private InputStream is = null;
private IUserDao userDao = null;
private SqlSession session = null;
/**
* 初始化
* @throws IOException
*/
@Before //测试开始前执行
public void init() throws IOException {
//1.解析xml配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.构建工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.工厂生产SqlSession对象
session = factory.openSession();
//4.创建代理Dao的对象
userDao = session.getMapper(IUserDao.class);
}
@After //测试结束后执行
public void destory(){
session.commit();
//7.释放资源
if( session != null){
session.close();
}
if( is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@org.junit.Test
public void testSelect() throws IOException {
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
//6.遍历对象
for (User user : users) {
System.out.println(user);
}
}
@org.junit.Test
public void testSave() throws IOException {
User user = new User();
user.setUsername("liuzeyu");
user.setBirthday(new Date());
user.setAddress("莆田");
user.setSex("男");
System.out.println("保存前:"+user);
userDao.save(user);
System.out.println("保存后:"+user);
}
@org.junit.Test
public void testUpdate() throws IOException {
User user = new User();
user.setId(48);
user.setUsername("duyangting");
user.setBirthday(new Date());
user.setAddress("厦门");
user.setSex("女");
userDao.update(user);
}
@org.junit.Test
public void testDelete() throws IOException {
userDao.delete(46);
}
@org.junit.Test
public void testFindOne() throws IOException {
User user = userDao.findById(42);
System.out.println(user);
}
@org.junit.Test
public void testFindOneByName() throws IOException {
List<User> users = userDao.findByName("%王%");//使用的是PreparedStatement的查询方式,Preparing: select * from user where username like ?
// List<User> users = userDao.findByName("王"); //使用的是拼接字符串的查询方式,Preparing: select * from user where username like '%王%'
for (User user : users) {
System.out.println(user);
}
}
@org.junit.Test
public void testFindTotal() throws IOException {
int total = userDao.findTotal();
System.out.println(total);
}
}
```
2. 多个对象组成一个查询条件
- 将user 对象使用类QueryStringVo包装
/** * 将查询条件封装到一个类中 */ public class QueryStringVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
- 在SqlMapConfig.xml向数据库中查询条件
</select>
<!-- 根据queryStringVo查询-->
<select id="findByVo" resultType="com.liuzeyu.domin.User" parameterType="com.liuzeyu.vo.QueryStringVo">
select * from user where username like #{user.username}
<!-- select * from user where username like '%${value}%' -->
</select>
-
测试函数(结果与模糊查询一致)
@org.junit.Test public void testFindOneByVo() throws IOException { QueryStringVo vo = new QueryStringVo(); User user = new User(); user.setUsername("%王%"); vo.setUser(user); List<User> users = userDao.findByVo(vo);//使用的是PreparedStatement的查询方式,Preparing: select * from user where username like ? for (User u : users) { System.out.println(u); } }
3. OGNL表达式介绍
OGNL :Object Graphic Navigation Lanuage (对象图导航语言)
它是通过对象取值方法来获取数据的,在写法上把类似JavaBean的get方法给删掉了。
类中的写法 user.getUsername
OGNL表达式:user.username
例如上面的
<insert id="save" parameterType="com.liuzeyu.domin.User">
insert into user (username,birthday,sex,address)VALUES (#{username},#{birthday},#{sex},#{address})
</insert>
由于parameterType属性已经提供了类的路径,则要获取values的username需要之需要写User类的属性即可#{username},否则需要写user.username
类似于:
<!-- 根据queryStringVo查询-->
<select id="findByVo" resultType="com.liuzeyu.domin.User" parameterType="com.liuzeyu.vo.QueryStringVo">
select * from user where username like #{user.username}
<!-- select * from user where username like '%${value}%' -->
</select>
4. 数据库表字段和实体类属性不一致问题
解决方法有两个:
方法一:通过对发送的sql语句字段名取别名来处理
<!-- 打印user表数据 -->
<select id="findAll" resultType="com.liuzeyu.domin.User">
<!-- 取别名来和实体类产生关系 -->
<!--SELECT id as userId,username as userName,address as userAddress,birthday as userBirthday ,sex as userSex from user -->
</select>
其中userId,userName,userAddress,userBirthday ,userSex 是实体类的属性。
对应的数据库列名:id,username,address,birthday,sex
这样查询出来的结果的字段名就是userId,userName,userAddress,userBirthday ,userSex ,此时就与实体类一一对应了。
方法二:通过配置文件来实现:
<!-- 配置查询的列名和实体类直接的对应关系-->
<resultMap id="userMap" type="com.liuzeyu.domin.User">
<!-- 主键id对应,property="userId"实体类属性, column="id"数据库列字段名-->
<id property="userId" column="id"/>
<!-- 非主键字段的对应关系-->
<result property="userName" column="username"/>
<result property="userAddress" column="address"/>
<result property="userBirthday" column="birthday"/>
<result property="userSex" column="sex"/>
</resultMap>
在操作数据库的标签内添加resultMap属性引用即可,如:
<!-- 打印user表数据 -->
<select id="findAll" resultType="com.liuzeyu.domin.User" resultMap="userMap">
SELECT * from USER
</select>
方法一比方法二的执行效率更高,但是方法二比方法一开发效率更高,就是说当项目比较大时,使用方法二会提高开发效率。
5. 优化主配置文件
- 引用外部连接数据库的连接信息
在主配置文件下< configuration >标签内部添加properties 的resource配置或url配置引用外部配置文件
<!-- 配置标签内部的属性连接数据库的信息,可以通过引用外部资源文件-->
<!--1. resource的配置方式-->
<!--<properties resource="jdbcConfig.properties">-->
<!--</properties>-->
<!--2. url的配置方式-->
<!--
url 与 uri的区别
url:uniform resource locator 统一资源定位 唯一标识一个资源的位置
写法:
协议://主机:端口/uri
http://localhost:80/servlet/index
uri:uniform resource Identifier 统一资源标识 在应用中唯一定位一个资源
-->
<properties url="file:\\\C:\Users\lzy\IdeaProjects\day02_mybatis_modify\src\main\resources\jdbcConfig.properties">
</properties>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis
jdbc.username=root
jdbc.password=809080
之后再JDBC的连接池里面以$获取实际配置文件中的值
<!-- JDBC连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
- 为标签属性取别名
取完别名后,可以再映射配置文件中直接使用
<!--自定义为配置文件取别名-->
<typeAliases>
<!--<typeAlias type="com.liuzeyu.domin.User" alias="user"/>-->
<package name="com.liuzeyu.domin"/>
</typeAliases>
<mark>使用typeAlias 标签去别名和package有一个区别?</mark>
typeAlias 指定type对象后,alias是别名,并且再映射配置文件中使用它可以不区分大小写,如:
package标签是指定取别名的包,当指定后,该包下<mark>所有的实体类</mark>都会被指定别名,并且类名就是别名,不再区分大小写。
-
简化主配置的映射接口配置
<mappers> <!--<mapper resource="com/liuzeyu/dao/IUserDao.xml"></mapper>--> <package name="com.liuzeyu.dao"></package> </mappers>
上面这种配置有一个好处是,再package标签下指定dao接口所在的包,就可以不用再写mapper以及class和resource属性了,它可以直接找到映射配置文件