MyBatis1
MyBatis 简介
概念:Mybatis 开源免费框架.原名叫iBatis,2010在googlecode,2013年迁移到github
作用: 数据访问层框架。底层是对 JDBC 的封装.
优点:使用mybatis时不需要编写实现类,只需要写需要执行的sql命令。
环境搭建
1.导入jar包
2. 在 src 下新建全局配置文件(编写 JDBC 四个变量)
1)没有名称和地址要求
2)在全局配置文件中引入 DTD 或 schema
3)全局配置文件内容
<transactionManager/>中 type 属性可取值
JDBC 事务管理使用 JDBC 原生事务管理方式
MANAGED 把事务管理转交给其他容器.原生 JDBC 事务相当于setAutoMapping(false);(不自动提交)
<dataSouce/>中 type 属性
POOLED 使用数据库连接池
UNPOOLED 不使用数据库连接池,和直接使用 JDBC 一样
JNDI:java 命名目录接口技术
<?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> <!-- default引用environment的id,当前所使用的环境 --> <environments default="default"> <!-- 声明可以使用的环境 --> <environment id="default"> <!-- 使用原生JDBC事务 --> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssm"/> <property name="username" value="root"/> <property name="password" value="smallming"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/su/mapper/FlowerMapper.xml"/> </mappers> </configuration>
3. 新建以 mapper 结尾的包,在包下新建:实体类名+Mapper.xml
1)文件作用:编写需要执行的 SQL 命令
2)把 xml 文件理解成实现类
3)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"> <!-- namesapce:理解成实现类的全路径(包名+类名) --> <mapper namespace="a.b" > <!-- id:方法名 parameterType:定义参数类型 resultType:返回值类型. 如果方法返回值是list,在resultType中写List的泛型,因为mybatis 对jdbc封装,一行一行读取数据 --> <select id="selAll" resultType="com.su.pojo.Flower"> select * from flower </select> </mapper>
4. 测试结果(只有在单独使用mybatis时使用,最后ssm整合时下面代码不需要编写.)
1)service中:
/** * 在数据访问层处理异常和在控制器中处理异常,service中只抛出异常. * @author Administrator * */ public class FlowerServiceImpl implements FlowerService { @Override public List<Flower> show() throws IOException { InputStream is = Resources.getResourceAsStream("mybatis.xml"); //前面是'工厂设计模式'。实例化工厂对象时使用的是'构建者设计模式',名称标志:后面有Builder //构建者设计模式意义: 简化对象实例化过程 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //生产 SqlSession SqlSession session = factory.openSession(); List<Flower> list = session.selectList("a.b.selAll"); session.close(); return list; } }
2)servlet中:
//大部分注解都有默认属性,如果注解中只给默认属性复制,可以省略属性名 //否则在注解的(属性名=属性值)格式 //如果一个属性是数组类型格式: 属性名={值,值} ,如果该数组只有一个值,可以省略大括号 //如果类型不是基本数据类型或String而是一个类类型,语法: 属性名=@类型 //注解中@表示引用注解声明
@WebServlet("/abc/b/show")
//@WebServlet(value={"/show"}) public class ShowServlet extends HttpServlet{ private FlowerService flowerService = new FlowerServiceImpl(); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<Flower> list = flowerService.show(); req.setAttribute("list", list); //相对路径 //只要路径中以/开头的都叫做全路径. 从项目根目录(WebContent)出发找到其他资源的过程 //只要不以/开头都是相对路径,相对路径是从当前资源出发找到其他资源的过程 //如果是请求转发 / 表示WebContent目录 //如果是重定向,静态资源引用,必须<img src=""/> <a href=""> <script src=""/> css引用时 其中 /都表示的是tomcat的webapps文件夹根目录 //服务器根目录 req.getRequestDispatcher("/index.jsp").forward(req, resp); } }
数据库连接池
1.在内存中开辟一块空间,存放多个数据库连接对象。
2.JDBCTomcatPool,直接由 tomcat 产生数据库连接池。
3.图示
active 状态:当前连接对象被应用程序使用中
Idle 空闲状态:等待应用程序使用
4.使用数据库连接池的目的
在高频率访问数据库时,使用数据库连接池可以降低服务器系统压力,提升程序运行效率。(小型项目不适用数据库连接池)
5.实现 JDBCtomcatPool 的步骤
在 web 项目的 META-INF 中存放 context.xml,在 context.xml 编写数据库连接池相关属性
把项目发布到 tomcat 中,数据库连接池就产生了。
<?xml version="1.0" encoding="UTF-8"?> <Context> <Resource driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/ssm" username="root" password="smallming" maxActive="50" maxIdle="20" name="test" <!--别名,调用使用--> auth="Container" <!--表示数据库连接池由tomcat管理(还可能由应用程序管理)--> maxWait="10000" <!--最长时间等待,未响应后返回异常--> type="javax.sql.DataSource" /> </Context>
6.可以在 java 中使用 jndi 获取数据库连接池中对象
Context:上下文接口.context.xml 文件对象类型
代码:
@WebServlet("/pool") public class DemoServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { //获取context.xml文件对象 Context cxt = new InitialContext(); //获取数据库池对象 DataSource ds = (DataSource) cxt.lookup("java:comp/env/test"); //获取连接对象 Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement("select * from flower"); ResultSet rs = ps.executeQuery(); res.setContentType("text/html;charset=utf-8"); PrintWriter out = res.getWriter(); while(rs.next()){ out.print(rs.getInt(1)+" "+rs.getString(2)+"<br/>"); } out.flush(); out.close(); rs.close(); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
当关闭连接对象时,把连接对象归还给数据库连接池,把状态改变成 Idle
三种查询方式
适用于查询结果都需要遍历的需求
适用于返回结果只是变量或一行数据时
适用于需要在查询结果中通过某列的值取到这行数据的需求
Map<key,resultType 控制>
<?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"> <!-- namesapce:理解成实现类的全路径(包名+类名) --> <mapper namespace="a.b" > <!-- id:方法名 parameterType:定义参数类型 resultType:返回值类型. 如果方法返回值是list,在resultType中写List的泛型,因为mybatis对jdbc封装,一行一行读取数据 --> <select id="selAll" resultType="com.su.pojo.Flower"> select id,name name123,price,production from flower </select> <select id="selById" resultType="int"> select count(*) from flower </select> <select id="c" resultType="com.su.pojo.Flower"> select id,name name123,price,production from flower </select> </mapper>
在java中:
public class Test { public static void main(String[] args) throws IOException { InputStream is = Resources.getResourceAsStream("myabtis.xml"); //使用工厂设计模式 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //生产SqlSession SqlSession session=factory.openSession(); List<Flower> list = session.selectList("a.b.selAll"); for (Flower flower : list) { System.out.println(flower.toString()); } int count = session.selectOne("a.b.selById"); System.out.println(count); //把数据库中哪个列的值当作map的key Map<Object, Object> map = session.selectMap("a.b.c", "name123"); System.out.println(map); session.close(); } }
<settings>标签
1.在 mybatis 全局配置文件中通过<settings>标签控制 mybatis 全局开关
2.在 mybatis.xml 中开启 log4j
必须保证有 log4j.jar
在 src 下有 log4j.properties
<?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> <settings> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <package name="com.su.pojo" /> </typeAliases> <!-- default引用environment的id,当前所使用的环境 --> <environments default="default"> <!-- 声明可以使用的环境 --> <environment id="default"> <!-- 使用原生JDBC事务 --> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssm"/> <property name="username" value="root"/> <property name="password" value="smallming"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/su/mapper/PeopleMapper.xml"/> <mapper resource="com/su/mapper/PeopleMapper2.xml"/> </mappers> </configuration>
3.log4j 中可以输出指定内容的日志(控制某个局部内容的日志级别)
命名级别(包级别):<mapper>namespace 属性中除了最后一个类名
例如 namespace=”com.su.mapper.PeopleMapper” 其中包级别为com.su.mapper,需要在 log4j.propeties 中
先在总体级别调成 Error 不输出无用信息
在设置某个指定位置级别为 DEBUG
类级别
namespace 属性值 ,namespace 类名
方法级别
使用 namespace 属性值+标签 id 属性值
parameterType 属性
1. 在XXXMapper.xml中<select><delete>等标签的 parameterType 可以控制参数类型
2. SqlSession 的 selectList()和 selectOne()的第二个参数和 selectMap()的第三个参数都表示方法的参数.
在 Mapper.xml 中可以通过#{}获取参数
parameterType 控制参数类型
#{}获取参数内容
使用索引,从 0 开始 #{0}表示第一个参数
也可以使用#{param1}第一个参数
如果只有一个参数(基本数据类型或 String),mybatis对#{}里面内容没有要求只要写内容即可.
如果参数是对象#{属性名}
如果参数是 map 写成#{key}
<select id="selById" resultType="com.su.pojo.People" parameterType="int"> select * from people where id=#{0} </select>
People p = session.selectOne("a.b.selById",2); //查询id为2的用户信息
System.out.println(p);
3. #{} 和 ${} 的区别
#{} 获取参数的内容支持 索引获取,param1获取指定位置参数,并且 SQL 使用?占位符
${} 字符串拼接不使用?,默认找${内容}内容的 get/set 方法,如果写数字,就是一个数字
4. 如果在 xml 文件中出现 “<”,“>”,双引号 等特殊字符时可以使用XML 文件转义标签(XML 自身的)
<![CDATA[ 内容 ]]>
<select id="test" resultType="com.su.pojo.People" parameterType="int"> <![CDATA[ select * from people where id<#{0} ]]> </select>
5. mybatis 中实现 mysql 分页写法
?不允许在关键字前后进行数学运算,需要在代码中计算完成后传递到 mapper.xml 中
在 java 代码中计算
在java中:
//显示几个 int pageSize = 2; //第几页 int pageNumber = 2; //如果希望传递多个参数,可以使用对象或 map Map<String,Object> map = new HashMap<>(); map.put("pageSize", pageSize); map.put("pageStart", pageSize*(pageNumber-1)); List<People> p = session.selectList("a.b.page",map);
在PeopleMapper.xml中:
<select id="page" resultType="com.su.pojo.People" parameterType="map"> select * from people limit #{pageStart},#{pageSize} </select>
typeAliases 别名
1.系统内置别名: 把类型全小写
2.给某个类起别名
alias=”自定义”
mybatis.xml 中配置
<typeAliases> <typeAlias type="com.su.pojo.People" alias="peo"/> </typeAliases>
mapper.xml 中 peo 引用 People 类
<select id="page" resultType="peo" parameterType="map"> select * from people limit #{pageStart},#{pageSize} </select>
3.直接给某个包下所有类起别名,别名为类名,不区分大小写
mybatis.xml 中配置
<typeAliases> <package name="com.su.pojo" /> </typeAliases>
mapper.xml 中通过类名引用
<select id="page" resultType="People" parameterType="map"> select * from people limit #{pageStart},#{pageSize} </select>
MyBatis 实现新增
1. 概念
功能:从应用程序角度出发,软件具有哪些功能.
业务:完成功能时的逻辑.对应 Service 中一个方法
事务:从数据库角度出发,完成业务时需要执行的 SQL 集合,统称一个事务.
事务回滚.如果在一个事务中某个 SQL 执行事务,希望回归到事务的原点,保证数据库数据的完整性.
2. 在 mybatis 中默认是关闭了 JDBC 的自动提交功能
每一个 SqlSession 默认都是不自动提交事务.
session.commit()提交事务.
openSession(true);自动提交.相当于setAutoCommit(true);
3. mybatis 底层是对 JDBC 的封装
JDBC 中 executeUpdate()执行新增,删除,修改的 SQL.返回值 int,表示受影响的行数.
mybatis 中<insert><delete><update>标签没有 resultType 属性,认为返回值都是 int
4. 在 openSession()时 Mybatis 会创建 SqlSession 时同时创建一个Transaction(事务对象),同时 autoCommit 都为 false
如果出现异常,应该 session.rollback()回滚事务.
5. 实现新增的步骤
在 mapper.xml 中提供<insert>标签,标签没有返回值类型
<insert id="ins" parameterType="People"> insert into people values(default,#{name},#{age}) </insert>
通过 session.insert()调用新增方法
People p = new People();
p.setName("新增name1");
p.setAge(88);
int index1 = session.insert("a.b.ins", p); if(index1>0){ System.out.println("成功"); }else{ System.out.println("失败"); }
MyBatis 实现修改
在 mapper.xml 中提供<update>标签
<update id="upd" parameterType="People"> update people set name = #{name} where id = #{id} </update>
编写代码
People peo = new People(); peo.setId(4); peo.setName("王五"); int index = session.update("a.b.upd", peo); if(index>0){ System.out.println("成功"); }else{ System.out.println("失败"); } session.commit();
mybatis 实现删除
在 mapper.xml 提供<delete>标签
<delete id="del" parameterType="int"> delete from people where id = #{0} </delete>
编写代码
int del = session.delete("a.b.del",3); if(del>0){ System.out.println("成功"); }else{ System.out.println("失败"); } session.commit();