1、Mybatis框架-01
Mybatis框架-01
为什么要学mybatis
?
我们开发时的持久化层使用原生的jdbc
开发的时候,代码过于繁琐,有很多冗余的代码,大大影响了我们的开发效率,还会影响软件的影响效率。所以出现了许多持久化的框架来提高我们的开发效率和代码的优化。持久层的框架有 Mybatis、Hibernate、JPA Java、SpringData-JPA、Spring框架的jdbctemplate
。
为什么要选用Mybatis
框架呢?
当我们的业务过于复杂的时候,早期的自动化生成的sql语句已经满足不了我们的需求了,所以我们需要手动写sql语句然后其余的交给框架来做。而Mybatis
就是这样的一个持久层的框架。
Mybatis入门
mybatis的运行流程图:
我们需要做的有:
-
配置
mybatis
的主配置文件,命名为mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- 声明xml --> <!-- xml的约束:http://mybatis.org/dtd/mybatis-3-config.dtd --> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- mybatis的根标签 --> <configuration> <!-- environments:环境配置的根标签 default:默认使用子标签的哪一个,根据子标签的id来决定 --> <environments default="mysql"> <!-- environment:environments的一个子标签,用来配置数据库的 id:标识environment 当id与default一致时,environments只会执行当前的environment environment可以有多个,一般情况一个就够了 --> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver" /> <!-- 注意要用转义 & 代替& --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf-8&"/> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- mappers:用来映射持久化层的 resource:需要配置所要映射的全限定名 --> <mappers> <mapper resource="cn/zj/mybatis/mapper/UserMapper.xml"/> </mappers> </configuration> -
创建一个
MybatisUtils
的工具类:用来创建sqlSessionFactory
来得到SqlSession
对象package cn.zj.mybatis.util; 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; /** * mybatis的工具类 * @author lgx * */ public class MybatisUtils { private static SqlSessionFactory factory; /* * 创建SqlSessionFactory */ static { //加载mybatis配置文件 String resource = "mybatis-config.xml"; //try (所要释放的资源),省去finally块 try (InputStream inputStream = Resources.getResourceAsStream(resource)){ factory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //创建sqlSession对象 public static SqlSession openSqlSession() { //调用SqlSessionFactory对象的openSession()来创建 SqlSession session = factory.openSession(); return session; } //测试创建的sqlSession public static void main(String[] args) { SqlSession session = openSqlSession(); System.out.println(session); } } -
创建持久化层(mapper/dao)
-
创建一个对应数据表的
XXXMapper.java
文件的接口public interface UserMapper { int insert(User user); } -
创建一个对应
XXXMapper.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:需要映射的持久化接口的全限定名 子标签: select:查询的标签 insert:插入的标签 update:修改的标签 delete:删除的标签 --> <mapper namespace="cn.zj.mybatis.mapper.UserMapper"> <!-- 插入一条数据 id:标识cn.zj.mybatis.mapper.UserMapper下的方法名来调用哪个方法 pramaterType:你所要插入的参数类型,写全限定名 OGNL语法: #{name},name可以是map的key,也可以pojo的属性 --> <insert id="insert" parameterType="cn.zj.mybatis.pojo.User"> insert into user (name,password,age) values (#{name},#{password},#{age}) </insert> </mapper> -
必须保持三个一致或四个一致
- 保持
mapper
的namespace
与对应的持久化层接口全限定名一致 - 保持
insert
等增删改查的标签的id与映射接口的方法名一致 - 保持
insert
等增删改查的标签的pramaterType
与方法的参数的返回值的全限定名保持一致 - 保持
XXXMapper.java
与XXXMapper.xml
的文件名一致
- 保持
-
-
创建一个test包来存放测试
xxxTest.java
的测试方法public class UserMapperTest { public static void main(String[] args) { //调用mybatisUtils工具类创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); //调用sqlSession的getMapper()获取到接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(null,"旺财","wangcai",18); //调用mapper代理对象对应的方法 int row = userMapper.insert(user); System.out.println(row); //手动提交事务 session.commit(); //关闭连接 session.close(); } }
日志框架
我们在开发过程中难免会出现错误,或者项目上线的时候出现了错误,所以我们要知道哪里出现了问题。
通过控制台输出的方式是没有办法将日志储存起来的。出现了许多可以记录日志的框架。
比如:
slf4j-log4j12-1.7.25
commons-logging-1.2
log4j-1.2.17
log4j2
Log4j的使用
log4j是什么?
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
为什么要用log4j?
答:Log4J框架的功能更加强大,注意表现为一下三点
\1. 可以通过配置实现不仅仅在控制台输出到控制台,也可以输出到文件
\2. 可以通过日志级别指定输出日志
\3. 可以通过参数指定输出日志的格式
下载路径:http://logging.apache.org/log4j/1.2/download.html
目录的说明
配置log4j
Log4J的配置文件(Configuration File)就是用来设置记录器的级别、存放器和布局的,它可接key=value格式的设置或xml格式的设置信息。通过配置,可以创建出Log4J的运行环境。
log4j
配置文件
# Global logging configuration log4j.rootLogger=ERROR, stdout # MyBatis logging configuration... #配置:log4j.logger+所要监听的日志= 日志的等级 #日志的等级(5个):TRACE/ALL(任何时候),info(普通信息),warn (报警告),debug(调试模式,项目没有上线开发),error(错误) log4j.logger.cn.zj.mybatis.mapper=TRACE # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
#配置根Logger log4j.rootLogger = [ level ] , appenderName1 , appenderName2 , … #配置日志信息输出目的地Appender log4j.appender.appenderName = fully.qualified.name.of.appender.class log4j.appender.appenderName.option1 = value1 … log4j.appender.appenderName.optionN = valueN #配置日志信息的格式(布局) log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1 = value1 … log4j.appender.appenderName.layout.optionN = valueN
日志级别:
FATAL 致命错误 ERROR 错误 WARN 警告 INFO 信息 DEBUG 调试
输出日志到目的地
org.apache.log4j.ConsoleAppender(控制台), org.apache.log4j.FileAppender(文件), org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件), org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件), org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
输出日志的格式:
org.apache.log4j.HTMLLayout(以HTML表格形式布局), org.apache.log4j.PatternLayout(可以灵活地指定布局模式), org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串), org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
打印的参数说明:
%m 输出代码中指定的消息 %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL %r 输出自应用启动到输出该log信息耗费的毫秒数 %c 输出所属的类目,通常就是所在类的全名 %t 输出产生该日志事件的线程名 %n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n” %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},输出类似:2002年10月18日 22 : 10 : 28 , 921 %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )
1.1. 在代码中初始化Logger
1)在程序中调用BasicConfigurator.configure()方法:给根记录器增加一个ConsoleAppender,输出格式通过PatternLayout设为"%-4r [%t] %-5p %c %x - %m%n",还有根记录器的默认级别是Level.DEBUG.
2)配置放在文件里,通过命令行参数传递文件名字,通过PropertyConfigurator.configure(args[x])解析并配置;
3)配置放在文件里,通过环境变量传递文件名等信息,利用log4j默认的初始化过程解析并配置;
4)配置放在文件里,通过应用服务器配置传递文件名等信息,利用一个特殊的servlet来完成配置。
\3. 为不同的 Appender 设置日志输出级别:
当调试系统时,我们往往注意的只是异常级别的日志输出,但是通常所有级别的输出都是放在一个文件里的,如果日志输出的级别是BUG!?那就慢慢去找吧。
这时我们也许会想要是能把异常信息单独输出到一个文件里该多好啊。当然可以,Log4j已经提供了这样的功能,我们只需要在配置中修改Appender的Threshold 就能实现,比如下面的例子:
[配置文件]
### set log levels ### 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 = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n ### 输出到日志文件 ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = logs/log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG ## 输出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 ### 保存异常信息到单独文件 ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File = logs/error.log ## 异常日志文件名 log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR ## 只输出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
[代码中使用]
public class TestLog4j { public static void main(String[] args) { PropertyConfigurator.configure( " D:/Code/conf/log4j.properties " ); Logger logger = Logger.getLogger(TestLog4j. class ); logger.debug( " debug " ); logger.error( " error " ); } }
运行一下,看看异常信息是不是保存在了一个单独的文件error.log中
Log4j2 ,因为log4j的配置文件是Properties的。工具无法提升的它的标签。Log4j2注意就是将配置文件修改为XML的!!
一个简单的CRUD案例
mapper.java
public interface UserMapper { //DML语句--------- //添加一条记录 int insert(User user); //修改一条记录 int updateByPrimaryKey(User user); //删除一条记录 int deleteByPrimaryKey(Integer id); //-------------- //DQL--------- //根据用户查询一条记录 User selectOne(User user); //查询所有 List<User> selectAll(); }
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"> <!-- mapper:根标签 namespace:需要映射的持久化接口的全限定名 子标签: select:查询的标签 insert:插入的标签 update:修改的标签 delete:删除的标签 --> <mapper namespace="cn.zj.mybatis.mapper.UserMapper"> <!-- 插入一条数据 id:标识cn.zj.mybatis.mapper.UserMapper下的方法名来调用哪个方法 pramaterType:你所要插入的参数类型,写全限定名 OGNL语法: #{name},name可以是map的key,也可以pojo的属性 --> <insert id="insert" parameterType="cn.zj.mybatis.pojo.User"> insert into user (name,password,age) values (#{name},#{password},#{age}) </insert> <!-- 修改一条数据 keyColumn : 数据表中主键对应的列 keyProperty :数据表对应的主键列对应pojo中属性的名称 useGeneratedKeys :是否返回数据库自动生成的主键给pojo属性,true 是,false 不是 --> <update id="updateByPrimaryKey" parameterType="cn.zj.mybatis.pojo.User" keyColumn="id" keyProperty="id" useGeneratedKeys="true" > update user set name = #{name}, password = #{password}, age = #{age} where id = #{id} </update> <!-- 删除一条记录 parameterType:这里的Integer内置了别名可以不需要我们去写一些常用基本数据类型,只需要写别名就可以了 --> <delete id="deleteByPrimaryKey" parameterType="Integer"> delete from user where id = #{id} </delete> <!-- 根据用户信息,查询一个用户 resultType:返回的类型,就是数据库查询到数据后自动封装到pojo对象中 需要写全限定路径 --> <select id="selectOne" parameterType="cn.zj.mybatis.pojo.User" resultType="cn.zj.mybatis.pojo.User"> select * from user where name = #{name} and password = #{password} </select> <!-- 查询所有 --> <select id="selectAll" parameterType="cn.zj.mybatis.pojo.User" resultType="cn.zj.mybatis.pojo.User"> select * from user </select> </mapper>
test
package cn.zj.mybatis.test; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import cn.zj.mybatis.mapper.UserMapper; import cn.zj.mybatis.pojo.User; import cn.zj.mybatis.util.MybatisUtils; public class UserMapperTest { // 用Junit单元测试工具 // 插入测试 @Test public void testInsert() { // 调用mybatisUtils工具类创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); // 调用sqlSession的getMapper()获取到接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(null, "旺财", "wangcai", 18); // 调用mapper代理对象对应的方法 int row = userMapper.insert(user); System.out.println(row); // 手动提交事务 session.commit(); // 关闭连接 session.close(); } // 修改测试 @Test public void testUpdate() { // 1.创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); // 2.调用getMapper()得到代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); // 3.调用代理对象的update() User user = new User(7, "大黄", "dahuang", 18); int row = userMapper.updateByPrimaryKey(user); System.out.println(row); // 4.提交事务 session.commit(); // 5.关闭连接 session.close(); } // 删除测试 @Test public void testDelete() { // 1.创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); // 2.调用getMapper()得到代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); // 3.调用代理对象的删除方法 int row = userMapper.deleteByPrimaryKey(8); System.out.println(row); // 4.提交事务 session.commit(); // 5.关闭连接 session.close(); } // 查询一条测试 @Test public void testSelectOne() { // 1.创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); // 2.调用getMapper()获取代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); // 3.通过代理对象调用查询方法 User conditionUser = new User(); conditionUser.setName("乔峰"); conditionUser.setPassword("123"); User resultUser = userMapper.selectOne(conditionUser); System.out.println(resultUser); // 不需要提交事务,这样会影响sql的查询性能 // 4.关闭连接 session.close(); } //查询所有 @Test public void testSelectAll() { //1.创建sqlSession SqlSession session = MybatisUtils.openSqlSession(); //2.调用getMapper得到代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); //3.调用代理对象查询所有的方法 List<User> users = userMapper.selectAll(); for (User user : users) { System.out.println(user); } //4.关闭连接 session.close(); } // public static void main(String[] args) { // //调用mybatisUtils工具类创建sqlSession对象 // SqlSession session = MybatisUtils.openSqlSession(); // //调用sqlSession的getMapper()获取到接口的代理对象 // UserMapper userMapper = session.getMapper(UserMapper.class); // User user = new User(null,"旺财","wangcai",18); // //调用mapper代理对象对应的方法 // int row = userMapper.insert(user); // System.out.println(row); // //手动提交事务 // session.commit(); // //关闭连接 // session.close(); // } }
使用了Junit的测试工具
需要导包或者开发工具已经集成了的。目前最新为5x,我们只需要使用4x就行了。
后台开发人员使用的只有一个@Test
注解
@Test public void testInsert() { // 调用mybatisUtils工具类创建sqlSession对象 SqlSession session = MybatisUtils.openSqlSession(); // 调用sqlSession的getMapper()获取到接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(null, "旺财", "wangcai", 18); // 调用mapper代理对象对应的方法 int row = userMapper.insert(user); System.out.println(row); // 手动提交事务 session.commit(); // 关闭连接 session.close(); }
运行一个光标移到对应的方法名上,运行全部光标移到空白初,运行的都是Junit方式。
成功时是绿色的条,有bug时是红色的条。
手动映射(resultMap)
查询所有 当我们查询出来的字段跟实体类的属性不一致时,一般是一致的,假如我们需要给他取别名呢? 所有我们需要手动映射:resultMap
自动映射:resultType="对应的实体类全限定名"
<!-- resultMap:手动映射 id:标识当前的手动映射 type: 手动映射的实体类的权限名 --> <resultMap id="userMap" type="cn.zj.mybatis.pojo.User"> <!-- column:查询出来数据库的列名 property:所要映射的实体类对象的属性 javaType:java中属性的类型【可选】 jdbcType:数据库对象的类型【可选】 javaType、jdbcType一般来说是一致的,可以不写 --> <id column="u_id" property="id" /> <!-- id和result没有区别,只是id是主键列,result是非主键列 --> <result column="u_name" property="name" /> <result column="u_password" property="password" /> </resultMap> <select id="selectAll" parameterType="cn.zj.mybatis.pojo.User" resultMap="userMap"> select id u_id, name u_name, password u_password, age from user </select>
主配置文件细节问题
在configuration
配置的标签是有顺序的:这里配置是有顺序的,鼠标移至configuration下的 Content Model 的顺序
<?xml version="1.0" encoding="UTF-8"?> <!-- 声明xml --> <!-- xml的约束:http://mybatis.org/dtd/mybatis-3-config.dtd --> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- mybatis的根标签 --> <configuration> <!-- ?表示0-1个 *表示0-n个 +表示至少1个到n个 什么都没有表示1个 --> <!-- 这里配置是有顺序的,鼠标移至configuration下的 Content Model 的顺序 --> <!-- properties配置数据库的配置文件 --> <properties resource="db.properties"></properties> <!-- 用来配置Mybatis的内部信息,比如是否缓存,是否开启事务,等等 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等 --> <settings> <!-- mapUnderscoreToCamelCase:是否开启驼峰命名规则,默认不开启false --> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> <!-- 配置别名:对于在参数选择时总是要写全限定名是不是太过于长了 所以我们要设置自己的别名 系统给我们配置了常用到的别名, --> <!-- typeAliases 配置别名 --> <typeAliases> <!-- typeAlias 配置一个 --> <typeAlias type="cn.zj.mybatis.pojo.User" alias="User"/> <!-- 通过扫描包的形式 --> <!-- <package name="cn.zj.mybatis.pojo"/> --> </typeAliases> <!-- environments:环境配置的根标签 default:默认使用子标签的哪一个,根据子标签的id来决定 --> <environments default="mysql"> <!-- environment:environments的一个子标签,用来配置数据库的 id:标识environment 当id与default一致时,environments只会执行当前的environment environment可以有多个,一般情况一个就够了 --> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}" /> <!-- 注意要用转义 & 代替& --> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <!-- mappers:用来映射持久化层的 resource:需要配置所要映射的全限定名 --> <mappers> <mapper resource="cn/zj/mybatis/mapper/UserMapper.xml" /> </mappers> </configuration>
settings:
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。
设置参数 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType 属性来覆盖该项的开关状态。 |
true | false | false |
aggressiveLazyLoading | 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods ). |
true | false | false (true in ≤3.4.1) |
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 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | 任意正整数 | Not Set (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | Not Set (null) |
safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。 If allow, set the false. | true | false | False |
safeResultHandlerEnabled | 允许在嵌套语句中使用分页(ResultHandler)。 If allow, set the false. | true | false | True |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回null 。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始) |
true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
vfsImpl | 指定VFS的实现 | 自定义VFS的实现的类全限定名,以逗号分隔。 | Not set |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters 选项。(从3.4.1开始) |
true | false | true |
configurationFactory | Specifies the class that provides an instance of Configuration . The returned Configuration instance is used to load lazy properties of deserialized objects. This class must have a method with a signature static Configuration getConfiguration() . (Since: 3.2.3) |
A type alias or fully qualified class name. | Not set |
完整的配置:
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
注解的开发
目前正在趋于注解式的开发,简化了我们不用对节点进行繁琐的操作。也是目前正在向往的趋势。
只需要通过注解可以完成对数据库的操作,注意需要将xml
文件删了或者注释代码。
xxxMapper.java
package cn.zj.mybatis.mapper; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import cn.zj.mybatis.pojo.User; public interface UserMapper { // DML语句--------- // 添加一条记录 @Insert("insert into user (name,password,age) values (#{name},#{password},#{age})") @Options(keyProperty = "id", useGeneratedKeys = true) // keyProperty:插入后就可以返回id了 int insert(User user); // 修改一条记录 @Update(" update user set name = #{name}, password = #{password}, age = #{age} where id = #{id} ") int updateByPrimaryKey(User user); // 删除一条记录 @Delete(" delete from user where id = #{id} ") int deleteByPrimaryKey(Integer id); // -------------- // DQL--------- // 根据用户查询一条记录 @Select(" select * from user where name = #{name} and password = #{password} ") User selectOne(User user); // 查询所有 @Select(" select id u_id, name u_name, password u_password, age from user ") @Results({ @Result( id = true, column = "u_id", property="id" ), @Result( column = "u_name", property="name" ), @Result( column = "u_password", property="password" ) }) List<User> selectAll(); }
需要改变主配置文件所映射的路径
改为:class的方式
<mappers> <mapper class="cn.zj.mybatis.mapper.UserMapper"/> </mappers>
@Param解决多个参数传入的问题
我们的参数传递写在OGNL语法上的#{}
括号里面的是Map集合的key
或者是实体类对应的属性
在jdk1.7以前是不支持反射获取参数名的,所以形参不能够获取到对应得名字,传进来就变成实参了,
所以要想传多个参数进来,就必须通过@Param
注解就其转为Map的key
@Select(" select * from user where name = #{name} and password = #{password} ") User selectUserByNameAndPassword(@Param("name") String name, @Param("password") String password);
当传递多个参数使用xml
文件的方式时,传递参数的类型为parameterType="map"
,因为传递时使用@Param注解的底层就是封装成HashMap
对象
#{}和${}的区别
${}和#{}都是OGNL语法,都可以完成对数据库的表数据进行增删查改的操作。
${}是用在拼接字符串的形式,且不带数据类型,用在对表数据的增删改查存在安全问题。
#{}是用来占位的占位符,所以对表数据的增删查改预防了sql注入的安全隐患。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!