框架基本概念及MyBatis框架
1.框架的概述
框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是被应用开发者定制的应用骨架。
2.开发分层的重要性
框架的重要性在于它实现了部分功能,并且能够很好的将底层应用平台和高层业务逻辑进行了缓和,为了实现软件工程中“高内聚,低耦合:。把问题划分开来解决,易于控制,易于延展,易于分配资源
3.分层开发的常见框架
MyBatis框架
解决数据的持久化问题
springMVC
解决web层问题的MVC框架
spring框架
解决技术整合问题的框架
4.MyBatis框架概述
mybatis是一个基于java的持久层框架,它内部封装了jdbc,使开发者只需关注sql语句本身
不需要花费精力去处理加载驱动,创建连接,创建statement等繁杂过程
mybatis通过xml或注解的方式执行各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射最终执行sql语句,最后又mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,是我们不用与jdbc api打交道,就可以完成对数据的持久化操作
5.mybatis框架入门操作
搭建mybatis开发环境
1.创建普通的Maven工程
2.在 pom.xml 文件中添加 Mybatis3.4.5 的坐标,如下:
还要添加单元测试jar包,数据库驱动jar包,log4j日志jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>www.yuan.</groupId>
<artifactId>mybatis_demo1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>
3.在 www.yuan.domain 包下编写实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//get set 方法略 自己补上
}
4.在www.yuan.dao 包下编写接口 IUserDao
IUserDao 接口就是我们的持久层接口(也可以写成 UserDao 或者 UserMapper),具体代码如下:
public interface IUserDao {
//查询所有用户
List<User> findAll();
public abstract void save(User user);
}
6.编写持久层接口的映射文件 IUserDao.xml
1.要求:
创建位置:必须和持久层接口在相同的包中。
名称:必须以持久层接口名称命名文件名,扩展名是.xml
2.在maven工程的resources目录下创建org/westos/dao 这个三级目录,然后在这个目录下
创建IUserDao.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="www.yuan.dao.IUserDao">
<select id="findAll" resultType="www.yuan.domain.User">
select *from list;
</select> //查询
<insert id="save" parameterType="www.yuan.domain.User">
insert into list(username,password)values (#{username},#{password});
</insert>//插入
</mapper>
7.编写MyBatis的核心配置文件 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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!--配置数据源的四个基本参数-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/lianxi"/>
<property name="username" value="root"/>
<property name="password" value="1"/>
</dataSource>
</environment>
</environments>
<!--配置dao接口的映射文件-->
<mappers>
<mapper resource="www/yuan/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
8.编写测试类
public class TEST { //查询
@Test
public void testFind() throws IOException {
//读取核心配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//构建工厂
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
//打开Sqlsession
SqlSession sqlSession = build.openSession();
//获取接口的代理对象
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
//执行查询结果
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
in.close();
sqlSession.close();
}
}
public class TEST { //插入
@Test
public void test() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = build.openSession();
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
mapper.save(user);
sqlSession.commit();
in.close();
sqlSession.close();
}
}
入门案例总结
通过入门案例发现,只需要编写Dao接口并且按照mybatis要求写两个配置文件,就可以实现功能。
注意事项
1.创建Iuserdao.xml和Iuserdao.java时名称是为了和我们之前的知识保持一致
在mybatis中它把持久层的操作接口名称和映射文件也叫作;MAPPER
所以:IUserdao和IuserMapper是一样的
2.:mybatis的映射配置文件位置必须和dao接口的包结构相同
3.映射配置文件的mapper标签namespace属性的值必须是dao接口的全限定类名
4.映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
采用注解的方式进行测试
@Before 在 @Test之前使用,只需调用一次配置文件
@Test 在测试的时候用
@after 在测试之后使用 释放资源
public class TEST2 {
private SqlSession sqlSession;
private InputStream in;
@Before
public void peizhi() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
sqlSession = build.openSession();
}
@Test
public void test() {
IUserdao mapper = sqlSession.getMapper(IUserdao.class);
User user = new User();
user.setUsername("妞妞");
user.setPassword("111111");
mapper.save(user);
sqlSession.commit();
}
@After
public void later() throws IOException {
in.close();
sqlSession.close();
}
}
采用注解的方式查询用户
1.删除映射文件IUserdao.xml
2.修改核心配置文件SqlMapConfig.xml
<mappers> //注解方式不需要映射文件
<mapper Rescourse="www.yuan.dao.IUserdao.xml"></mapper>
</mappers>
<mappers>//修改为CLASS属性来引入接口全路径
<mapper class="www.yuan.dao.IUserdao"></mapper>
</mappers>
更新与删除用户
<mapper namespace="www.yuan.dao.IUserdao">
<update id="update" parameterType="www.yuan.domain.User">
update list set username=#{username},password=#{password}where id=#{id};
</update>
<delete id="delete" parameterType="www.yuan.domain.User">
delete from list where id=#{id};
</delete>
</mapper>
public interface IUserdao {
void update(User user);
void delete(User user);
}
public class test {
private SqlSession sqlSession;
private InputStream in;
@Before
public void peizhi() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
sqlSession = build.openSession();
}
@Test
public void test(){
IUserdao mapper = sqlSession.getMapper(IUserdao.class);
User user = new User();
user.setId(4);
user.setUsername("张峰");
user.setPassword("0000");
mapper.update(user);;
sqlSession.commit();
}
@Test
public void test2(){
IUserdao mapper = sqlSession.getMapper(IUserdao.class);
User user = new User();
user.setId(1);
mapper.delete(user);
sqlSession.commit();
}
@After
public void later() throws IOException {
in.close();
sqlSession.close();
}
}
查询单个用户
测试
@Before
public void peizhi() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
sqlSession = build.openSession();
}
@Test
public void test3(){
IUserdao mapper = sqlSession.getMapper(IUserdao.class);
User user = new User();
user.setId(3);
User single = mapper.findSingle(user);
System.out.println(single);
}
@After
public void later() throws IOException {
in.close();
sqlSession.close();
}
}
接口
public interface IUserdao {
User findSingle(User user);
}
映射文件
<select id="findSingle" resultType="www.yuan.domain.User" >
select*from list where id=#{id};
</select>
模糊查询
public interface IUserDao{
List<User>likeSelect(String username);
}
<select id="likeSelect" resultType="www.yuan.domain.User" parameterTYpe="string">
select*from user where username like #{uname};
</select>
@Test
public void test(){
IUserDao dao = sqlSession.getMapper(IUserDao.class);
List<User> list = dao.likeUserByUsername("%张%");
for (User user : list) {
System.out.println(user);
}
}
获取自增长键的值
加入保存一个用户时,想获取数据的自增长键的值
利用mysql的一个函数
select LAST_INSERT_ID();
在映射文件中保存用户的操作中添加配置
<insert id="save" parameterType="org.westos.domain.User">
获取自增长键的值
<selectKey keyProperty="id" keyCOlum="id" resultType="int" order="AFTER">
SELECT LAST_insert_id();
</selectkey>
insert into user(username, password)
values (#{username}, #{password});
</insert>
keyProperty="id" 实体类中的id表示自增长键
keyColumn="id" 表中的主键名
resultType="int" 返回类型
order="AFTER" 在插入后获取自增长的值
public class TEST { //插入
@Test
public void test() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = build.openSession();
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
mapper.save(user);
sqlsession.commit() //提交事务
INteger id =user.getId();
sout(id);
}
parameterType传入参数的类型
sql语句传参,使用标签的parameterType属性来设定
该属性的取值可以是基本类型,引用类型,也可以是实体类类型(POJO类)
同时也可以使用实体类的包装类。
开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其他的查询条件
这时可以使用包装对象传递输入参数。pojo类中包含pojo
1.创建一个QueryVo类,类中维护着一个User对象
public class QueryVo{
User user;
}
在接口中提供查询方法,方法的参数要一个QueryVO类型
public interface IUserDao{
//根据VO模糊查询
List<User> likeUserByVO(queryVO vo);
}
在映射文件中添加配置
<select id="likeUserByVO" ResultType="www.yuan.domain.User" parameterType="www.yuan.domain.QueryVO">
select*from list where username like #{user.username}
</select>
说明:#{user.username} user是QueryVO中的属性 会通过反射调用getUser()获取User的对象
username 是User中的属性,会通过getUsername来获取值
测试
@Test
public void test(){
IUserDao dao = sqlSession.getMapper(IUserDao.class);
User user = new User();
user.setUsername("%王%");
QueryVO queryVO = new QueryVO();
//把User对象设置给VO
queryVO.setUser(user);
List<User> list = dao.likeUserByVO(queryVO);
for (User user1 : list) {
System.out.println(user1);
}
}
实体类的属性名和表中的字段名不一致
public class User implements Serializable{
private String user_name;
private String user_word;
private Integer user_id;
}
在映射文件中配置实体类的属性名和表中字段名的对应关系
<resultMap id="myMap" type="www.yuan.domain.User">
<!--配置实体类和表中主键的对应关系-->
<id property="user_name" colum="username"></id>
<!--配置其他普通字段的对应关系-->
<result property="user_name" colum="username"></result>
<result property="user_word" colum="password"></result>
</resultMap>
修改返回数据类型的配置
<select id="select" resultMap="myMap">
select *from list;
</select>
resultMap="myMap" 这是引用我们映射配置
使用properties标签引用外部的配置文件
在核心配置文件sqlMapConfig.xml里面有连接数据库的4个基本参数配置
可以把这4个配置单独写在一个外部配置文件中
在resources目录下新建一个文件jdbcConfig.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/list
username=root
password=1
在SqlMapConfig.xml中使用<properties>标签引入外部配置文件
注意:resource是引用类路径下的配置文件,这个标签放到<configuration>标签里面的最前面
<properties rescource="jdbcConfig.properties">
</properties>
4.修改<dataSource> 标签中的配置
注意:value的值要和外部配置文件中的键名保持一致
<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>
给实体类起别名
我们回到sqlmapconfig.xml中使用<typealiases>标签给实体类起个别名
<typeAliases>
<typeAliasses type="www.yuan.domain.User" alias="user"><typeALiases>
</typeALiases>
这个别名使用在可以写user或者Use 或者USER都行
使用package标签扫描该包下所有接口
如果一个包下的接口太多一个一个去扫描麻烦,那么可以使用
<package>标签 扫描该包下所有的接口
<mappers>
<!-- <mapper resource="org/westos/dao/IUserDao.xml"></mapper>-->
<!--扫描该包下所有的dao接口-->
<package name="org.westos.dao"></package>
</mappers>
password" value="${jdbc.password}"/>
### 给实体类起别名
```java
我们回到sqlmapconfig.xml中使用<typealiases>标签给实体类起个别名
<typeAliases>
<typeAliasses type="www.yuan.domain.User" alias="user"><typeALiases>
</typeALiases>
这个别名使用在可以写user或者Use 或者USER都行
使用package标签扫描该包下所有接口
如果一个包下的接口太多一个一个去扫描麻烦,那么可以使用
<package>标签 扫描该包下所有的接口
<mappers>
<!-- <mapper resource="org/westos/dao/IUserDao.xml"></mapper>-->
<!--扫描该包下所有的dao接口-->
<package name="org.westos.dao"></package>
</mappers>