1.原生态jdbc编程中的问题总结
1.1jdbc程序
1.1.1jdbc是什么?
JDBC英文名为:Java Data Base Connectivity(Java数据库连接),官方解释它是Java编程语言和广泛的数据库之间独立于数据库的连接标准的Java API(applacation programming inferce应用程序编程接口),根本上说JDBC是一种规范,它提供的接口,一套完整的,允许便捷式访问底层数据库。可以用JAVA来写不同类型的可执行文件:JAVA应用程序、JAVA Applets、Java Servlet、JSP等,不同的可执行文件都能通过JDBC访问数据库,又兼备存储的优势。简单说它就是JAVA与数据库的连接的桥梁或者插件,用JAVA代码就能操作数据库的增删改查、存储过程、事务等。
1.1.2jdbc的缺点
- SQL代码夹在Java代码中,耦合度高导致代码硬编码内伤。
- 维护不易且实际开发需求过程中sql的需求时不断变化的,频繁修改的情况多变。
2.MyBatis的相关说明
2.1为什么要学习MyBatis
- 对开发人员而言,核心sql还是需要自己优化。
- sql和java编码分开,功能边界清晰,一个专注业务,一个专注数据。
2.2什么是MyBatis
- mybatis是一个优秀的Java持久层的框架,它内部封装了JDBC,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂过程。
- mybatis是通过xml或者注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象返回。
2.3相关文件下载
2.3.1MyBaits下载地址
说明:
2.3.2java与mysql连接jar包下载
下载地址:链接:https://pan.baidu.com/s/1hZEdWNa6qN1wBFMAnpTuKQ
提取码:jhb7
2.3.3Apache日志文件log4j下载
下载地址:链接:https://pan.baidu.com/s/1RwmL_CNy_AGIEBBGW37TRQ
提取码:v229
3.MyBatis_HelloWorld
3.1mysql数据库的相关操作
- 打开navicat数据库,新建一个数据库名为mybatis,在该数据库中新建一个表名为tbl_employee,表中相关设置如下:
- 打开表tbl_employee,设置一组初始值,例如:
3.2eclipse相关操作
- 代开eclipse新建一个Java工程名为MyBatis_01_HelloWorld,在该工程下创建一个名为Employee的类,并将其放在包com.dt.mybatis.bean下,代码如下:
package com.dt.mybatis.bean;
public class Employee {
private Integer id;
private String lastName;//这里设置一个不同于数据库中的名字,用于在后面的数据库查询中修改属性名
private String email;
private String gender;//为这四个变量添加get,set以及toString函数
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
}
}
- 在MyBatis_01_HelloWorld工程中新建一个名为lib的包,在该包中导入log4j-1.2.17.jar,mybatis-3.4.1.jar,mysql-connector-java-5.1.37-bin.jar三个jar包(这三个包均在之前下载的文件中),其中log4j-1.2.17.jar包的作用为方便在控制台查看mybatis打印的数据库的相关文件,并且要想使用该包必须配置一个名为log4j.xml的文件(注意这里的名称为硬性要求),导入这三个包后还不能直接使用需要进行相关的配置:具体操作如下:
在MyBatis_01_HelloWorld中创建一个包名为conf,在该包中创建log4j.xml,创建方式为:
打开log4j.xml并在其中添加如下代码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' >
<!--对于ConsoleAppender来说,在开发阶段还是比较有用的,能直接在ide中看到输出的日志内容,
但是在实际的产品阶段,我们更希望将日志输出到指定的文件上查看,这就需要用到FileAppender-->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %l %m%n" />
</layout>
<!--如果有过滤器,当前appender只会处理满足过滤器条件的日志信息-->
<!--<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="DEBUG" />
<param name="levelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>-->
</appender>
<!-- 写到远端日志 -->
<appender name="DEFAULT-APPENDER-REMOTE" class="org.apache.log4j.net.SyslogAppender">
<param name="SyslogHost" value="${logServer}"/>
<param name="Facility" value="LOCAL1"/>
<param name="FacilityPrinting" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %c %m%n" />
</layout>
</appender>
<appender name="FRAMEWORK-APPENDER-REMOTE" class="org.apache.log4j.net.SyslogAppender">
<param name="SyslogHost" value="${logServer}"/>
<param name="Facility" value="LOCAL3"/>
<param name="FacilityPrinting" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %c %m%n" />
</layout>
</appender>
<!-- 写到本地日志 -->
<!--第一步:配置appender-->
<appender name="INFO-LOCAL" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/opt/logs/info.log" />
<param name="append" value="true" /><!--一般必须配置true,否则会覆盖而不是累加-->
<param name="encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %l %m%n" />
</layout>
<!--如果有过滤器,日志文件中就只会有符合过滤器的日志信息-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="DEBUG" />
<param name="levelMax" value="INFO" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="ERROR-LOCAL" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/opt/logs/error.log" />
<param name="append" value="true" /><!--一般必须配置true,否则会覆盖而不是累加-->
<param name="encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %t %l %m%n" />
</layout>
<!--如果有过滤器,日志文件中就只会有符合过滤器的日志信息-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="WARN" />
<param name="levelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<!--第二步:配置logger。
如果不配置,系统会采用默认策略,即additivity="true",level value="DEBUG"。
注意:additivity=true,表示遵循缺省的继承机制,此时就不应该继续配置appender-ref,否则日志会出现重复
相反,如果additivity=false,就必须要配置appender-ref,否则日志不会被打印,配置也就没有意义-->
<logger name="com.test.log4j" additivity="true">
<!--给具体的logger配置日志级别,比如com.test包下面日志级别大于等于DEBUG的,
才会交给appender进行处理。
注意:对于com.test包而言,此处的级别会覆盖root下面的日志级别-->
<level value="INFO" />
<!--如果此处配置了append-ref,而且additivity="true",将会和root里面的同一个
append-ref形成累加,即重复日志-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="DEFAULT-LOCAL"/>-->
<!--<appender-ref ref="ERROR-LOCAL"/>-->
</logger>
<logger name="com.test2" additivity="false">
<level value="INFO" />
<appender-ref ref="INFO-LOCAL" />
</logger>
<!--第三步:配置root-->
<!--root的作用是收集所有配置的logger反馈上来的信息流并根据配置在root中appender进行输出,
只要你在looger中配置了additivity="false",就不会反馈到root中。-->
<root>
<!--优先级小于具体的logger中配置的级别,只有当具体的logger没有配置的时候,
这里才会对具体的looger起作用-->
<level value="DEBUG" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO-LOCAL" />
<appender-ref ref="ERROR-LOCAL"/>
</root>
</log4j:configuration>
说明:xml是Extensible Markup Language的简称,为扩展性标识语言,文件的后缀名为:.xml。就像HTML的作用是显示数据,XML的作用是传输和存储数据,为了便于不同应用、不同平台之间的数据共享和通信。
- 在conf文件夹下新建一个.xml文件,命名为:mybatis-config.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" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root" />
<property name="password" value="1333" />
</dataSource>
</environment>
</environments>
<!-- 前面写好的映射文件一定要注册到全局配置文件中(映射文件就是EmployeeMapper.xml,配置文件就是mybatis-config.xml) -->
<mappers>
<mapper resource="EmployeeMapper.xml"/><!-- 这里写 EmployeeMapper.xml的路径-->
</mappers>
</configuration>
注意:
- 创建一个mybatis的测试类,重命名为MyBatisTest.java,并将其放在包com.dt.mybatis.test下
向其中导入如下代码:
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";//引号内部书写工程中mybatis的配置文件的位置
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
然后对于该部分代码按住ctrl+shift+o键,然后选择java.io.inputStream,接着选择org.apache.ibatis.io.Resources,对于有异常的部分进行抛出异常,相关截图如下:
说明:如何向java中插入已经下载的mybatis源码程序,用来查看相关函数的作用是什么: 将鼠标停靠在需要查看的函数上,然后点击open declaration,然后点击attach source,选择external location,点击external file选择下载好的mybatis源码包,点击OK即可。
添加如下代码:
package com.dt.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
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.Test;
import com.dt.mybatis.bean.Employee;
public class MyBatisTest {
/**
* 第一步:根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象
* @throws IOException
*/
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";//引号内部书写工程中mybatis的配置文件的位置
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession实例,能直接执行已经映射的sql语句
SqlSession openSession = sqlSessionFactory.openSession();
try{
//将返回的值封装到Employee类中的对象employee中
Employee employee = openSession.selectOne("com.dt.mybatis.EmployeeMapper.selectEmp", 1);//函数中第一个参数表示sql的唯一标识符,这里即为EmployeeMapper.xml中的唯一标识符,同时加上相应的命名空间用来防止存在同名的现象,第二个参数表示执行的参数对象
System.out.println(employee);
}finally{
openSession.close();
}
}
}
- 在conf文件夹下创建一个xml文件,重命名为EmployeeMapper.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="com.dt.mybatis.EmployeeMapper">
<!--
namespace:表示名称空间,可以任意取名,但最好顾名思义
id:唯一标识符,可以任意取名,但最好顾名思义
resultType:返回值类型,表示查出数据库中id的信息将其返回为一个对象,这里表示前面Employee.java中的Employee对象,故这里可以写Employee.java的位置
#{id}:表示从传过来的Id中取出id值,在MyBatisTest.java文件中的selectOne方法中第二个参数中具体写要查询的Id
-->
<select id="selectEmp" resultType="com.dt.mybatis.bean.Employee">
select id,last_name lastName,email,gender from tbl_employee where id = #{id}<!-- 这里为查询sql语句的写法,last_name lastName表示将属性的名字取别名为lastName -->
</select>
</mapper>
总结:综上所述,查出数据共有以下几步:
第一步:写一个全局配置文件(这里为mybatis-config.xml),该文件中有数据源一些运行环境的信息(这里为映射文件的信息:EmployeeMapper.xml)
第二步:写一个映射文件(这里为EmployeeMapper.xml),该文件配置每一个sql以及sql的封装规则等,然后写一个封装类(这里为Employee.java)
第三步:写代码,根据全局配置文件得到sqlSessionFactory,使用sqlSession工厂获取sqlSession对象,使用它来进行增删改查(这里为MyBatisTest.java)
4.MyBatis_接口式编(第二种查询数据库的方法)
- 创建一个接口命名为EmployeeMapper,输入以下内容:
package com.dt.mybatis.dao;
import com.dt.mybatis.bean.Employee;
public interface EmployeeMapper {
/**
* //定义一个函数用来查询sql并将其封装成Employee对象
* @param id
* @return
*/
public Employee getEmpById(Integer id);
}
- 在测试类MyBatisTest.java中做如下修改,修改后的代码为:
package com.dt.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
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.Test;
import com.dt.mybatis.bean.Employee;
import com.dt.mybatis.dao.EmployeeMapper;
public class MyBatisTest {
/**
* 第一步:根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象
* @throws IOException
*/
public SqlSessionFactory getSqlSessionFactory() throws IOException{
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
//第一种方法:不推荐
// @Test
// public void test() throws IOException {
// //String resource = "mybatis-config.xml";//引号内部书写工程中mybatis的配置文件的位置
// //InputStream inputStream = Resources.getResourceAsStream(resource);
// //SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// //获取sqlSession实例,能直接执行已经映射的sql语句
// SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// SqlSession openSession = sqlSessionFactory.openSession();
// try{
// //将返回的值封装到Employee类中的对象employee中
// Employee employee = openSession.selectOne("com.dt.mybatis.EmployeeMapper.selectEmp", 1);//函数中第一个参数表示sql的唯一标识符,这里即为EmployeeMapper.xml中的唯一标识符,同时加上相应的命名空间用来防止存在同名的现象,第二个参数表示执行的参数对象
// System.out.println(employee);
// }finally{
// openSession.close();
// }
// }
//第二种方法:接口式编程(我们建议采用这种方法,它拥有许多的优点,例如:更安全的类型检查)
@Test
public void test01()throws IOException{
//第一步:获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//第二步:获取sqlSession对象
SqlSession openSession = sqlSessionFactory.openSession();
try{
//第三步:获取接口的实现类对象
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
//第四步:查出数据库中id为1的值
Employee employee = mapper.getEmpById(1);
// //会为接口自动创建一个代理对象,代理对象去执行增删改查
// System.out.print(mapper.getClass());
//第五步:输出employee对象的值
System.out.print(employee);
}finally{
//第六步:关闭openSession
openSession.close();
}
}
}