1.mybatis基础知识
①. Jdbc的缺点
1.原始Jdbc的缺点所在(了解)
1>.原始jdbc操作(查询数据)
2>.原始jdbc操作(插入数据)
3>.
原始jdbc操作的分析
1.原始jdbc开发存在的问题如下:
- ①. 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能
- ②. sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变java代码
- ③. 查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置
2.应对上述问题给出的解决方案:
- ①. 使用数据库连接池初始化连接资源
- ②. 将sql语句抽取到xml配置文件中
- ③. 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射
②. Mybatis入门介绍
http://www.mybatis.org/mybatis-3/
1>.
什么是Mybatis
- ①. mybatis 是一个优秀的基于java的持久层框架
- ②. mybatis 可以隐藏jdbc繁杂的api
- ③. 我们只需要关注sql语句
- ④. mybatis自动完成实体对象和数据库表数据的映射关系
2>.
Mybatis的工作原理
1.读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置 文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接 2.加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL 语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,个配置文件对应数据库中的一张表 3.创建会话工厂。通过MyBatis的环境等配置信息构造会话工厂SqlSessionFactory 4.创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有 方法 5.MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的形参的所有 方法 6.在Execuotor接口的执行方法中,包含了一个MappedStatement类型的参数,该参数是对映射信息 的封装,用来存储要映射的SQL语句的id、参数等。Mapper.xml文件中的一个SQL对应一个 MappedStatement对象,SQL的id是MappedStatement的id 7.输入参数映射。在执行方法时,MapperStatement对象会对用户执行SQL语句的输入参数进行定义 (可以定义为Map、List、基本数据类型和POJO类型),Executor执行器会通过MappedStatement对象在 执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对 PreparedStatement对象设置参数的过程 8.输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进 行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通过MappedStatement 对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于 JDBC编程中对结果的解析处理过程
3>.
MyBatis入门程序
- ①. 导入MyBatis的坐标和其他相关坐标
<!--mybatis坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!--mysql驱动坐标--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> <scope>runtime</scope> </dependency> <!--单元测试坐标--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--日志坐标--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency>
- ②. 编写User实体
public class User { private int id; private String username; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
- ③.编写UserMapper映射文件
<?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="userMapper"> <select id="findAll" resultType="com.itheima.domain.User"> select * from User </select> </mapper>
- ④. 编写MyBatis核心文件
<!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"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///test"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/itheima/mapper/UserMapper.xml"/> </mappers> </configuration>
- ⑤. 编写测试代码
/*查询所有*/ @Test public void test1()throws Exception{ //1.加载配置文件 InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml"); //2.获取工厂对象 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); //3.创建会话对象 SqlSession sqlSession=sqlSessionFactory.openSession(); //4.执行操作 List<User>list=sqlSession.selectList("userMapper.findAll"); System.out.println(list); //5.释放资源 sqlSession.close(); }
- ⑥. log4j.properties
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c:/mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=debug, stdout
4>.
MyBatis的增删改查操作
1.
抽取工具类
public class MybatisUtils { /*私有构造方法*/ private MybatisUtils(){} private static SqlSessionFactory sqlSessionFactory; static { try { //1.加载配置文件 InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml"); //2.给SqlSessionFactory工厂赋值 sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //3.获取sqlSession会话对象 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2.
查询[ 查询所有、通过id进行查询、模糊查询 ]
<!--查询所有的对象--> <select id="findAll" resultType="com.itheima.domain.User"> select * from user </select> <!--根据id进行查询--> <select id="findUserById" parameterType="Integer" resultType="com.itheima.domain.User"> select * from user where id=#{id} </select> <!--模糊查询--> <select id="findUserByName" parameterType="String" resultType="com.itheima.domain.User"> select * from user where username like concat('%',#{value},'%') </select>
/*1.查询所有*/ @Test public void SelectAll()throws Exception{ //1.加载配置文件 InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml"); //2.获取SqlSesiionFactory会话工厂 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); //3.创建sqlSession会话对象 SqlSession sqlSession=sqlSessionFactory.openSession(); //4.执行操作 List<User>list=sqlSession.selectList("userMapper.findAll"); System.out.println(list); //5.释放资源 sqlSession.close(); } /*2.通过id查询用户信息*/ @Test public void selectById()throws Exception{ //1.加载配置文件 InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml"); //2.创建SqlSessionFactory工厂对象 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); //3.创建SqlSession会话对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.执行sql User user=sqlSession.selectOne("userMapper.findUserById",1); System.out.println(user); //5.释放资源 sqlSession.close(); } /*3.根据姓名进行模糊查询*/ @Test public void selectByName()throws Exception{ //1.获取会话对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //2.执行sql List<User> list = sqlSession.selectList("userMapper.findUserByName", "x"); System.out.println(list); }
3.
添加一个用户
#{id}
:从输入user对象中获取id属性值
<!--插入数据--> <insert id="insertUser" parameterType="com.itheima.domain.User"> insert into user(id,username,password)values(#{id},#{username},#{password}) </insert>
/*4.新增一条User记录*/ @Test public void add()throws Exception{ //1.获取会话对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //2.执行sql //2.1 创建User对象 User user=new User(); user.setId(5); user.setUsername("xiaozhi"); user.setPassword("123"); int row=sqlSession.insert("userMapper.insertUser",user); System.out.println(row); //3.进行事务的提交 sqlSession.commit(); //4.释放资源 sqlSession.close(); }
4.
修改
<!--修改--> <update id="updateUser" parameterType="com.itheima.domain.User"> update user set username=#{username},password=#{password} where id=#{id} </update>
/*5.修改*/ @Test public void update()throws Exception{ //1.获取会话对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //2.执行sql User user=new User(); user.setId(1); user.setUsername("xiaoxing"); user.setPassword("123456"); int result=sqlSession.update("userMapper.updateUser",user); System.out.println(result); //3.进行事务的提交 sqlSession.commit(); //4.释放资源 sqlSession.close(); }
5.
通过id进行删除
<!--删除--> <delete id="deleteById" parameterType="java.lang.Integer"> delete from user where id=#{id} </delete>
/*6.删除*/ @Test public void delete()throws Exception{ //1.获取会话对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //2.执行sql int result=sqlSession.delete("userMapper.deleteById",5); System.out.println(result); //3.进行事务的提交 sqlSession.commit(); //4.释放资源 sqlSession.close(); }
5>.
知识点总结[ 掌握 ]
1.
映射文件[ UserMapper.xml]
<mapper namespace="test"> <select id="findCustomerById" parameterType="Integer" resultType="com.itcast.mybatis.po.User"> select * from user where id = #{id} </select> </mapper>
- ①. namespace命名空间:作用就是对sql进行分类化管理,理解sql隔离。通常会设置成包名+sql映射文件名注意:使用namespace代理方式开发,namespace有特殊的作用
- ②. 通过select执行数据查询<select id="" parameterType="" resultType="">
1.id:标识映射文件的sql,称为statement的id [将sql语句封装mappedStatement对象中,所以将id称为statement的id ] 2.#{}:表示占位符,相当于? 3.#{id}:其中的id表示 接收输入的参数,参数名称是id,如果输入参数是简单类型, #{}中的参数名可以任意 ,可以value或其他名称 4.parameterType:指定输入参数类型,这里指定int型 5.resultType:指定sql输出结果的映射的java类型,resultType表示将单条记录映射成的java对象
2.
parameterType 和 resultType
- ①. parameterType:在映射文件中通过parameterType指定输入 参数的类型
- ②. resultType:在映射文件中通过resultType指定输出结果的类型
3.
selectOne(statement,parament)和selectList(statement,parament)
- ①. 第一个参数statement:映射文件中statement的id,等于=namaspace+statementId
- ②. 第二个参数parament:指定和映射文件中所匹配paramtype类型的参数(输入参数)
- ③. session.selectOne 结果是与映射文件中所匹配的resultType类型的对象
4.
selectOne和selectList
- ①. selectOne:表示查询出一条记录进行映射。如果使用了selectOne可以实现,那么使用selectList也可以实现 [ List中只有一个对象 ]
- ②. selectList:表示查询出一个列表 [ 多个列表 ] 进行映射,如果使用了,如果使用selectList要查询多天记录,不能使用selectOne
5.
模糊查询注意事项
- ①. 第一种情况是字符串的拼接,会引起sql注入,不推荐使用
1.select * from user where username like ‘%${value}%’ 2.select * from user where username like concat('%',#{value},'%')
- ②. #{ } 和 ${ }
#{ }: 1.#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo等 2.如果接受简单类型,#{}里面的可以写成value或其他的 3.#{}接受的是pojo。要通过 user.user.username的形式获取 ${ }: 1.表示一个拼接符号,会引起sql注入,所以不建议使用 2.${ } 接受输入参数,类型可以是简单类型,pojo等 3.${ } 接受的是pojo。要通过 user.user.username的形式获取
6>.
Mybatis的核心对象
1.
SqlSessionFactory
- 作用:创建SqlSession对象
String resource = "org/mybatis/builder/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream);
SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用执行期间都会存在。如果我们 多次地创建同一个数据库的SqlSessionFactory,那么数据库的资源将很容易被消耗。为了解决此 问题,通常每一个数据库都只对应同一个SqlSessionFactory,所以在构建SqlSessionFactory实 例时,建议使用单列模式
2.
SqlSession会话对象
SqlSession 是一个加强版的Connection,所以用完后要关闭资源 1.执行语句的方法主要有: <T> T selectOne(String statement, Object parameter) <E> List<E> selectList(String statement, Object parameter) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter) 2.操作事务的方法主要有: void commit() void rollback() 注意:在增删改中都要进行事务的提交 3.<T>T getMapper(Class<T>type):[重点] 该方法会返回Mapper接口的代理对象,该对象关联了SqlSession对象,开发人员可以使用该对象 直接调用方法操作数据库。参数type是Mapper接口类型。Mybatis官方推荐通过Mapper对象访问Mybatis
3.
使用工具类创建SqlSession
public class MybatisUtils { /*私有构造方法*/ private MybatisUtils(){} private static SqlSessionFactory sqlSessionFactory; static { try { //1.加载配置文件 InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml"); //2.给SqlSessionFactory工厂赋值 sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //3.获取sqlSession会话对象 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
7>.
MyBatis常用配置解析
1.
environments标签
- 数据库环境的配置,支持多环境配置
1.其中,事务管理器(transactionManager)类型有两种:[掌握JDBC] •JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作 用域。 •MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命 周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因 此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。 2.其中,数据源(dataSource)类型有三种:[掌握POOLED] •UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。 •POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。 •JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部 配置数据源,然后放置一个 JNDI 上下文的引用。
2.
mapper标签
- 该标签的作用是加载映射的,加载方式有如下几种:
<mappers><mappers> 1.使用相对于类路径的资源引用,例如:[重点掌握] <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> 2.使用映射器接口实现类的完全限定类名,例如: <mapper class="org.mybatis.builder.AuthorMapper"/> 3.将包内的映射器接口实现全部注册为映射器,例如: <package name="org.mybatis.builder"/> 4.使用完全限定资源定位符(URL),例如: <mapper url="file:///var/mappers/AuthorMapper.xml"/>
3.
Properties标签
- 实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件
4.
typeAliases标签
- ①. 类型别名是为Java 类型设置一个短的名字。原来的类型名称配置如下
- ②. 配置typeAliases,为com.itheima.domain.User定义别名为user。如果省略alias,mybatis会默认将类名首字母小写后的名称作为别名
- ③. 当pojo类过多时,还可以通过自动扫描包的形式自定义别名,具体如下
//mybatis会将所有的com.itheima.domain下的类以首字母变小写为它的包名。 //比如com.itheima.domain.User 那么它的别名是user <typeAliases> <package name="com.itheima.domain"> </typeAliases>
- ④. 上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名
<?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> <!--通过properties标签加载外部properties文件--> <properties resource="jdbc.properties"></properties> <!--自定义别名--> <typeAliases> <typeAlias type="com.itheima.domain.User" alias="user"></typeAlias> </typeAliases> <!--数据源环境--> <environments default="developement"> <environment id="developement"> <transactionManager type="JDBC"></transactionManager> <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> </environment> </environments> <!--加载映射文件--> <mappers> <mapper resource="com/itheima/mapper/UserMapper.xml"></mapper> </mappers> </configuration>