持久化是将程序数据在持久状态和瞬时状态间转换的机制。
为什么需要持久化服务呢?那是由于内存本身的缺陷引起的
ORM的全称是Object Relational Mapping,即对象关系映射。它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程。
简单点说,如果我们用的是面向对象的编程语言,数据库使用的数据库是关系型数据库,那么将面向对象的语言和面向关系型的数据库之间建立一种映射关系,这就是对象关系映射。
它赋予我们一个强大的功能,就是可以用面向对象的思维来操作数据库,不用再和SQL语句打交道了。
映射(Mapping),通过这种映射可以使业务对象与数据库分离。从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象。图 1简单说明了ORM在多层系统架构中的这个作用。
1、mybatis配置:
mybatis-config.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。mapper.xml文件即 sql 映射文件,文件中配置了操作数据库的 sql语句。此文件需要在mybatis-config.xml中加载。
2、通过mybatis环境等配置信息构造 SqlSessionFactory即会话工厂
3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession行。
4、mybatis 底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及 sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的 id。
6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement 在执行sql前将输入的java对象映射至 sql中,输入参数映射就是jdbc编程中对preparedStatement 设置参数。
7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
思路流程:搭建环境–>导入Mybatis—>编写代码—>测试
1、搭建实验数据库
2、导入MyBatis相关 jar 包
< <!-- 导入依赖-->
<dependencies>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 导入mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 导入 junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
3、编写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>
<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?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 每一个Mapper.XML都需要在mybatis核心配置文件中注册-->
<mappers>
<mapper resource="com/zsn/dao/userMapper.xml"/>
</mappers>
</configuration>
4、编写MyBatis工具类
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 java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
5、创建实体类
public class User {
private int id; //id
private String name; //姓名
private String pwd; //密码
//构造,有参,无参
//set/get
//toString()
}
6、编写Mapper接口类
import com.zsn.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> selectUser();
}
7、编写Mapper.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">
<!-- namespace=绑定一个对应的/Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserMapper">
<select id="selectUser" resultType="com.zsn.pojo.User">
select * from user
</select>
</mapper>
8、编写测试类
public class MyTest {
@Test
public void selectUser() {
//SqlSession 的实例不是线程安全的
SqlSession session = MybatisUtils.getSession();
//方法一:过时
//List users = session.selectList("com.kuang.mapper.UserMapper.selectUser");
//方法二:
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user);
}
//关闭
session.close();
}
}
9、运行测试,成功的查询出来的我们的数据,ok!
问题说明
可能出现问题说明:** Maven静态资源过滤问题(找不到xml)
maven由于他的约定大于配置,我们之后可以能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties
**/ *.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties
**/ *.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
Id:对应是namespace中的方法名(接口中的方法名)
resultType:返回值–>sql语句执行的返回值
parameterType:参数类型(方法中传入的参数)
注意:增删改需要提交事务
1、编写接口:
//根据id查询用户
User getUserId(int id);
2、编写对应的mapper中的SQL语句
<!-- 增加用户-->
<insert id="addUser" parameterType="com.zsn.pojo.User">
insert into mybatis.user (id, name , pwd) values (#{id},#{name },#{pwd});
</insert>
3、测试
public static void getUserId(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserId(1001);
System.out.println(user);
session.close();
}
1、编写接口:
//增加用户
int addUser(User user);
2、编写对应的mapper中的SQL语句
<!-- 增加用户-->
<insert id="addUser" parameterType="com.zsn.pojo.User">
insert into mybatis.user (id, name , pwd) values (#{id},#{name },#{pwd});
</insert>
3、测试
public static void addUser(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(1003, "王嬢嬢", "123546");
int result = mapper.addUser(user);
if(result>0){
System.out.println("用户添加成功");
}else{
System.out.println("用户添加失败");
}
//注意要提交事务
session.commit();
session.close();
}
1、编写接口:
//修改用户
int updateUser(User user);
2、编写对应的mapper中的SQL语句
<!-- 修改用户-->
<update id="updateUser" parameterType="com.zsn.pojo.User">
update user set name = #{name},pwd=#{pwd} where id = #{id};
</update>
3、测试
public static void updateUser(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(1003, "王嬢嬢", "123546");
int result = mapper.updateUser(user);
if(result>0){
System.out.println("用户修改成功");
}else{
System.out.println("用户修改失败");
}
session.commit();
session.close();
}
1、编写接口:
//删除用户
int deleteUser(int id);
2、编写对应的mapper中的SQL语句
<!-- 删除用户-->
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
3、测试
public static void deleteUser(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int result = mapper.deleteUser(1003);
if(result>0){
System.out.println("用户删除成功");
}else{
System.out.println("用户删除失败");
}
session.commit();
session.close();
}
注意:增删改需要提交事务
假设,我们的实体类,或者数据库中的表。字段或者参数过多是,我们应当考虑使用Map!
1、编写接口:
//删除用户
int addUser2(Map<String,Object> map);
2、编写对应的mapper中的SQL语句
这里的values后边传的参数名就可以不用和user中的属性名一一对应
<!-- 增加用户-->
<insert id="addUser2" parameterType="map">
insert into mybatis.user (id, name , pwd) values (#{userid},#{username},#{userpwd});
</insert>
3、测试
public static void addUser2(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("userid",1005);
map.put("username","诸葛青");
map.put("userpwd","987654");
int result = mapper.addUser2(map);
if(result>0){
System.out.println("用户添加成功");
}else{
System.out.println("用户添加失败");
}
//注意要提交事务
session.commit();
session.close();
}
Map传递参数,直接在SQL中取出key即可!
对象传递参数,直接在SQL中取对象的属性即可!
只有一个基本类型的参数的情况下,可以直接在SQL中取到
多个参数用Map或者注解
//模糊查询
List<User> getUserLike(String name);
1、Java代码执行的时候传递通配符
编写对应的mapper中的SQL语句
<select id="getUserLike" parameterType="String" resultType="com.zsn.pojo.User">
select * from user where name like #{value}
select>
测试代码:
public static void getUserLike(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("%王%");
Iterator<User> iterator = userList.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user);
}
session.close();
}
2、在SQL拼接中使用通配符!
编写对应的mapper中的SQL语句
<select id="getUserLike" parameterType="String" resultType="com.zsn.pojo.User">
select * from user where name like "%"#{value}"%"
select>
有SQL注入的风险!!!
测试代码:
public static void getUserLike(){
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("%王%");
Iterator<User> iterator = userList.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user);
}
session.close();
}
2、在SQL拼接中使用通配符!
核心配置文件
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!-- 注意元素节点的顺序!顺序不对会报错 -->
我们可以阅读 mybatis-config.xml 上面的dtd的头文件!
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
MyBatis 可以配置成适应多种环境,
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
每个数据库对应一个 SqlSessionFactory 实例
注意一些关键点:
默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]":
如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器
数据源(dataSource)
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
常用POOLED 即连接池
编写配置文件:
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456
在核心配置文件中映射:
<!- 引入外部位置文件-->
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
properties>
语法:
SQL语句xml文件(没有起别名)
<select id="getUserId" resultType="com.zsn.pojo.User" >
select * from user
select>
起别名后:
<select id="getUserList" resultType="User">
select * from user
select>
<typeAliases>
<package name="com.zsn.pojo"/>
typeAliases>
每一个在包 com.zsn.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 com.zsn.pojo.User 的别名为 user;若有注解(@Alias(“别名”)),则别名为其注解值。
用法:
实体类较少可以使用第一种
实例类多的可以用第二种
查看文档:
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 |
true | false | false |
aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods )。 |
true | false | false (在 3.4.1 及之前的版本中默认为 true) |
multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。NONE : 不做任何反应WARNING : 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN )FAILING : 映射失败 (抛出 SqlSessionException ) |
NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) | 未设置 (null) |
safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true | false | False |
safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) |
一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 null 。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) |
true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) |
true | false | true |
configurationFactory | 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) |
一个类型别名或完全限定类名。 | 未设置 |
shrinkWhitespacesInSql | 从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5) | true | false | false |
defaultSqlProviderType | Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type (or value ) attribute on sql provider annotation(e.g. @SelectProvider ), when these attribute was omitted. |
A type alias or fully qualified class name | Not set |
一个配置完整的 settings 元素的示例如下:
类型处理器(typeHandlers)
对象工厂(objectFactory)
插件(plugins)
定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句
引入资源方式
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!--
将包内的映射器接口实现全部注册为映射
但是需要配置文件名称和接口名称一致,并且位于同一目录
-->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
Mapper文件
方式一:推荐使用
<mappers>
<mapper resource="com/zsn/dao/UserMapper.xml"/>
mappers>
方式二:使用class文件绑定注册
<mappers>
<mapper resource="com.zsn.dao.UserMapper"/>
mappers>
注意:
方式三:使用扫描包进行绑定
<mappers>
<package name="com.zsn.dao"/>
mappers>
注意:
作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder
SqSessionFactory
SqlSession
属性名和字段名不一致查询出来的结果会为null
1、查看之前的数据库的字段名
2、Java中的实体类设计
public class User {
private int id; //id
private String name; //姓名
private String password; //密码和数据库不一样!
//构造
//set/get
//toString()
}
3、接口
//根据id查询用户
User selectUserById(int id);
4、mapper映射文件
<select id="selectUserById" resultType="user">
select * from user where id = #{id}
</select>
5、测试
@Test
public void testSelectUserById() {
SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
session.close();
}
结果:
分析:
select * from user where id = #{id} 可以看做
select id,name,pwd from user where id = #{id}
mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写) , 去对应的实体类中查找相应列名的set方法设值 , 由于找不到setPwd() , 所以password返回null ; 【自动映射】
解决:
1、起别名
<select id="selectUserById" resultType="User">
select id , name , pwd as password from user where id = #{id}
select>
2、使用结果集映射->ResultMap 【推荐】
<resultMap id="UserMap" type="User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
resultMap>
<select id="selectUserById" resultMap="UserMap">
select id , name , pwd from user where id = #{id}
select>
<resultMap id="UserMap" type="User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
resultMap>
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手。
以前排错:sout、debug
现在日志工厂:
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
---|---|---|---|
在Mybatis中具体使用哪一个日志实现,在设置中设定
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
1.先导入log4j的包
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
2、写log4j.properties配置文件
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
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 = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://JavaTools/log/log.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://JavaTools/log/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://JavaTools/log/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://JavaTools/log/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3、配置mybatis-config.xml文件
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
4、日志级别
每个Logger都被了一个日志级别(log level),用来控制日志信息的输出。日志级别从高到低分为:
A:off 最高等级,用于关闭所有日志记录。
B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
D:warm 表明会出现潜在的错误情形。
E:info 一般和在粗粒度级别上,强调应用程序的运行全程。
F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
G:all 最低等级,用于打开所有日志记录。
5、简单使用:
5.1、导包:
import org.apache.log4j.Logger;
5.2、设置全局变量
public static Logger log= Logger.getLogger(UserDaoTest.class);
5.3、输出
log.info("info:进入getUserList()方法");
log.error("info:进入getUserList()方法");
log.debug("info:进入getUserList()方法");
语法:
语法:select * from user limit startIndex,pageSize;
select * from user limit 0,3;
接口:
//分页
List<User> getUserByLimit(Map<String,Integer> map);
SQL:
<select id="getUserByLimit" parameterType="map" resultType="user" >
select * from user limit #{startIndex},#{pageSize}
select>
测试类:
public static void getUserByLimit(){
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String,Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize", 2);
List<User> userList = mapper.getUserByLimit(map);
for(User uesr:userList){
System.out.println(uesr);
}
session.close();
}
大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程。
根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好。
关于接口的理解
三个面向区别
mybatis最初配置信息是基于 XML ,映射语句(SQL)也是定义在 XML 中的。而到MyBatis 3提供了新的基于注解的配置。不幸的是,Java 注解的的表达力和灵活性十分有限。最强大的 MyBatis 映射并不能用注解来构建
简单语句可以使用注解,复杂语句使用xml配置文件,都推荐使用配置文件,易看,好维护
sql 类型主要分成 :
**注意:**利用注解开发就不需要mapper.xml映射文件了
1、在接口中添加注解
//查询全部用户
@Select("select * from user")
List<User> getUserList();
2、在mybatis-config.xml的核心配置文件中注入
<mappers>
<mapper class="com.kuang.mapper.UserMapper"/>
mappers>
3、测试
public static void getUserList(){
log.info("info:进入getUserList()方法");
//获取SqlSession对象
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
Iterator<User> iterator = userList.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user);
}
session.close();
}
4、本质上利用了jvm的动态代理机制。
1、编写接口方法
//根据id查询用户
@Select("select * from user where id = #{id}")
User selectUserById(@Param("id") int id);
2、测试
@Test
public void testSelectUserById() {
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
session.close();
}
1、编写接口方法
//添加一个用户
@Insert("insert into user (id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);
2、测试
@Test
public void testAddUser() {
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(6, "张灵玉", "123456");
mapper.addUser(user);
session.close();
}
1、编写接口方法
//根据id删除用
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id")int id);
2、测试
@Test
public void testDeleteUser() {
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
mapper.deleteUser(6);
session.close();
}
1、编写接口方法
//修改一个用户
@Update("update user set name=#{name},pwd=#{pwd} where id = #{id}")
int updateUser(User user);
2、测试
@Test
public void testUpdateUser() {
SqlSession session = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(6, "张起灵", "zxcvbn");
mapper.updateUser(user);
session.close();
}
【注意点:增删改一定记得对事务的处理】
@Param注解用于给方法参数起一个名字。以下是总结的使用原则:
#{}和${}都能取得简单的数据类型,pojo对象,map对象的值。
#,$如果取pojo对象的属性,那么需要和pojo的属性一致;如果取map的值,那么需要和map的key一致
#{} 的作用主要是替换预编译语句(PrepareStatement)中的占位符? 【推荐使用】
有效防止SQL注入
INSERT INTO user (name) VALUES (#{name});
INSERT INTO user (name) VALUES (?);
${} 的作用是直接进行字符串拼接
INSERT INTO user (name) VALUES ('${name}');
INSERT INTO user (name) VALUES ('kuangshen');
使用的时候一般都使用#{可以防止sql注入;但是也有必须要使用 的 情 况 〈 不 能 做 为 s q l 参 数 的 情 况 下 , 只 能 使 用 的情况〈不能做为sql参数的情况下,只能使用 的情况〈不能做为sql参数的情况下,只能使用,例如:根据XX进行排序,升序还是降序)
Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或eques等方法,同时可以自动化日志变量。
1、lombok下载
直接下载,重启idea
2、导入maven依赖
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
dependency>