MyBatis框架
-
MyBatis框架概述
mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,
而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中
sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并
返回。
采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我
们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
-
案例测试
2.1 配置pom.xml文件
<packaging>jar</packaging> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
2.2 编写实体类
public class User implements Serializable{ private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } }
2.3 编写持久层接口
public interface IUserDao { /** * 查询所有操作 */ List<User> findAll(); }
2.4 编写持久层接口的 映射文件:创建位置必须和持久层接口在相同的包,且名称以持久层接口 名称命名扩展名 是.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="cn.xiong.dao.IUserDao"> <!--配置查询所有--> <select id="findAll" resultType="user"> select * from user; </select> <mapper>
2.5编写SqlMapConfig.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"> <!-- mybatis的主配置文件 --> <configuration> <properties resource="jdbcConfig.properties"></properties> <!-- <properties url="file:///E:/IdeaProjects/MyBatis/src/main/resources/jdbcConfig.properties"></properties>--> <typeAliases><typeAlias type="cn.xiong.domain.User" alias="user"></typeAlias></typeAliases> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql的环境--> <environment id="mysql"> <!-- 配置事务的类型--> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <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> </environment> </environments> <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 --> <mappers> <package name="cn.xiong.dao"/> </mappers> </configuration>
2.6编写测试类
private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before public void init() throws Exception { in = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(true); userDao = sqlSession.getMapper(IUserDao.class); } @After public void destory() throws Exception { sqlSession.close(); in.close(); } @Test public void testFindAll() { List<User> users = userDao.findAll(); for (User user : users) { System.out.println(user); } }
-
基于代理Dao实现CRUD操作
要求:
1、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
2、SQL 语句的配置标签的 id 属性必须和持久层接口的
方法名相同。在Dao接口中添加方法
void saveUser(User user); /** * 修改方法 */ void updateUser(User user); /** * 删除方法 */ void deleteUser(Integer UserId); /** * 查找一个方法 */ User findById(Integer UserId); /** * 模糊查询方法 */ List <User> findByName(String username); /** * 查询总用户数方法 */ int findTotal();
在映射文件中配置
#{}表示一个占位符号,通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类
型值,#{}括号中可以是 value 或其它名称。
表 示 拼 接 s q l 串 , 通 过 {}表示拼接 sql 串,通过 表示拼接sql串,通过{}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值, 可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是 value。<insert id="saveUser" parameterType="user"> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> select last_insert_id(); </selectKey> insert into user (username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday}); </insert> <update id="updateUser" parameterType="user"> update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}; </update> <select id="deleteUser" parameterType="java.lang.Integer"> delete from user where id=#{id}; </select> <select id="findById" parameterType="INT" resultType="user"> select *from user where id=#{id}; </select> <select id="findByName" parameterType="java.lang.String" resultType="user"> select * from user where username like #{name}; </select> <select id="findTotal" resultType="int"> select count(id) from user; </select>
在测试类中实现方法
@Test public void testSave() throws IOException { User user = new User(); user.setUsername("李"); user.setAddress("xi"); user.setSex("男"); user.setBirthday(new Date()); System.out.println("保存之前" + user); userDao.saveUser(user); // sqlSession.commit(); System.out.println("保存之后" + user); } @Test public void testUpdate() { User user = new User(); user.setId(50); user.setUsername("李一雄"); user.setAddress("西安"); user.setSex("女"); user.setBirthday(new Date()); userDao.updateUser(user); } @Test public void testDelete() { userDao.deleteUser(51); userDao.deleteUser(52); } @Test public void testfindById() { User u1 = userDao.findById(48); User u2 = userDao.findById(49); System.out.println(u1); System.out.println(u2); } @Test public void testfindByName() { List<User> users = userDao.findByName("%李%"); for (User user : users) { System.out.println(user); } } @Test public void testfindTotal() { int i = userDao.findTotal(); System.out.println(i); }
传递pojo对象与动态sql语句
开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。Pojo 类中包含 pojo。
动态sql:比如在 id 如果不为空时可以根据 id 查询,
如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。编写QueryVo实体类
public class QueryVo { private User user; public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; } private List<Integer> ids; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
在Dao接口中添加方法
List<User> findUserByVo(QueryVo vo);
在映射文件中添加配置
<select id="findUserByVo" parameterType="cn.xiong.domain.QueryVo" resultType="user"> select * from user where username like #{user.username}; </select>
在测试类中实现方法
@Test public void testfindUserByVo() { QueryVo vo = new QueryVo(); User user = new User(); user.setUsername("%李%"); vo.setUser(user); List<User> users = userDao.findUserByVo(vo); for (User user1 : users) { System.out.println(user1); } }
MyBatis框架之sql动态查询
-
动态sql之if标签与where标签
if标签的 test 属性中写的是对象的属性名,
where标签用来简化开发
1.定义持久层接口Dao
public interface IUserDao {
List<User> findUserByCondition(User user);
}
2.配置xml文件
<select id="findUserByCondition" resultType="user" parameterType="user">
select * from user
<where>
<if test="username!=null">
and username=#{username}
</if>
<if test="sex!=null">
and sex=#{sex}
</if>
</where>
</select>
3.编写测试类
@Test
public void testfindByCondition() {
User u = new User();
u.setUsername("李");
u.setSex("女");
List<User> users = userDao.findUserByCondition(u);
for (User user : users) {
System.out.println(user);
}
}
-
foreach标签
标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符1.定义持久层接口Dao
List<User> findUserInIds(QueryVo vo);
2.配置xml文件
<select id="findUserInIds" resultType="user" parameterType="cn.xiong.domain.QueryVo"> select * from user <where> <if test="ids!=null and ids.size()>0"> <foreach collection="ids" open="and id in (" close=")" item="id" separator=","> #{id} </foreach> </if> </where> </select>
3.测试类
@Test public void testfindUserInIds(){ QueryVo vo = new QueryVo(); List<Integer> list =new ArrayList<Integer>(); list.add(41); list.add(43); list.add(50); list.add(51); vo.setIds(list); List<User> users = userDao.findUserInIds(vo); for (User user : users) { System.out.println(user); } }