标签:ref private block 事务管理 resources 字母 本地 false when
我这里有几个下载好的依赖包提供给大家
<!--导入依赖--> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> </dependency> </dependencies>
mybatis文档是这么说的,"每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。 "
用xml文件配置SqlSessionFactory ,在resouses工具类下,创建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/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false&severTimezone=gmt%2b8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
编写一个工具类去获取sqlSession对象,以后调用即可
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 MyBatisUtil { private static SqlSessionFactory sessionFactory; static { //获取获取SqlSesson工厂对象 String resouse = "mybatis-config.xml"; try { InputStream inputStream = Resources.getResourceAsStream(resouse); sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //返回sqlsession对象 public static SqlSession getSqlSession(){ return sessionFactory.openSession(); } }
一个与数据库表对应的资源类(提供gette、rsetter、构造方法、toString)
package pojo; public class User { private int id; private String name; public User() {} public User(int id, String name) {this.id = id;this.name = name;} public int getId() {return id;} public void setId(int id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} @Override public String toString() { return "User{" + "id=" + id + ", name=‘" + name + ‘\‘‘ + ‘}‘; } }
一个有获得结果集的抽象方法的接口
public interface UserDao { List<User> getUserList(); }
一个用来映射Sql语句的Mapper文件(提供Session与数据库的对接)
<?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="dao.UserDao"> <!--对应的语句写对应的标签,id为接口的方法,resultType为结果集--> <select id="getUserList" resultType="pojo.User"> select * from jdbcstudy.student; </select> </mapper>
package dao; import Utils.MyBatisUtil; import org.apache.ibatis.session.SqlSession; import pojo.User; import java.util.List; public class UserTest { @org.junit.Test//之前导入了junit的依赖 public void test(){ //通过工具类获取Sqlsession对象 SqlSession session = MyBatisUtil.getSqlSession(); //用SqlSession的getMappper方法获取实例类 UserDao userDao = session.getMapper(UserDao.class); //调用实例类方法 List<User> list = userDao.getUserList(); for (User user : list) { System.out.println(user); } session.closed(); } }
1.mapper文件未注册
org.apache.ibatis.binding.BindingException: Type interface dao.UserDao is not known to the MapperRegistry.
解决办法:
在配置SqlSessionFactory的xml文件中加入mapper注册
<mappers> <mapper resource="dao/UserMapper.xml"/> </mappers>
2.maven资源输出过滤问题
会报出未初始化和io未找到mapper.xml文件等错误
java.lang.ExceptionInInitializerError
Could not find resource dao/UserMapper.xml
解决办法:在项目配置文件里加入下列代码
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
输出结果:格式不正确可能是没有重写toString方法。楼主我就栽在了这坑里
mapper标签属性:
namespace:命名空间和接口保持一致
语句标签属性:
id:namespace对应接口中的方法
resultType:返回值类型
需要新的语句时,只需要在接口里新加入抽象方法、以及向mapper映射文件中加入sql语句标签即可
eg:根据id查询用户
接口抽象函数:
User getUserById(int id);//根据id查询用户
mapper映射标签:
<select id="getUserById" resultType="pojo.User"> select * from jdbcstudy.student where id= #{id}; </select>
Test测试:
@org.junit.Test public void SelectById(){ SqlSession session = MyBatisUtil.getSqlSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user= userMapper.getUserById(0); System.out.println(user); }
@org.junit.Test public void addUser(){ SqlSession session = MyBatisUtil.getSqlSession(); UserMapper userMapper = session.getMapper(UserMapper.class); int add = userMapper.addUser(new User(2,"赵中波")); if(add>0) System.out.println("修改成功"); //事务提交 session.commit(); session.close(); }
使用map传参要比基本类型传参和对象传参更加灵活,可以使用key值自定义属性名,在用value存储值,eg:
<insert id="addUser" parameterType="map"> insert into jdbcstudy.student (id,name) values (#{idkey},#{namekey}); </insert>
一般数据库里模糊查询是使用%,比如查询李姓用户 like ‘李%‘
myBatis里可以用字符串拼接,或是在传参时传入参数为("李%"),但这样就显得很low或是接口设计不良好,一般是在sql语句映射文件里用字符串拼接
<select id="getUserById" parameterType="int" resultType="pojo.User"> select * from jdbcstudy.student where id= #{id}"%"; </select> 或者是 <select id="getUserById" parameterType="int" resultType="pojo.User"> select * from jdbcstudy.student where id= concat(#{id},"%"); </select>
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下(配置的时候也要按这个顺序来):
1.事务管理器(transactionManager)
类型:jdbc(默认)、managed
2.数据源(datasourse)
类型:Pooled(默认,连接池)、Unpooled、Jdni(正常连接)
3.属性(properties)
属性可以在外部进行配置.properties文件,并可以进行动态替换。也可以在 properties 元素的子元素中设置。
优先级:类型传参>外部文件>子元素设置
4.别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写,这样配置时,别名可以在任何地方替代原类
<typeAliases> <typeAlias alias="Blog" type="domain.blog.Blog"/> </typeAliases>
比较实用的是用别名扫描一个包,比如原先我定位到一个累要用com.#.@.%.User,加入包扫描后就可以直接用user(首字母小写)定位该类
<typeAliases> <package name="com.#.@.%"/> </typeAliases>
5.映射器(mappers)
每个mapper映射器在使用前都需要注册
<mappers> <mapper resource="dao/UserMapper.xml"/>使用相对路径 <mapper url="D://UserMapper.xml"/>使用绝对路径 <mapper class="dao.UserMapper"/>使用类导入方式(mapper文件和该接口类同包且同名) <package name="dao"/>使用包导入方式(接口类和mapper文件同名) </mappers>
使用返回实体类类型的方式,如果类属性和数据库列名匹配不上(不同名)的话,就会出现查询出null的情况,为了解决这个问题,可以使用结果集映射
<resultMap id="name" type="class"> <result column="数据库列名" property="类属性名"/> <!--如果属性是对象,一般需要通过某个列名再去查询到该对象(多对一查询)--> <association column="映射对象的列名" property="对象属性名" javaType="对象类型" select="连接查询的id"> <result column="数据库列名" property="类属性名"/><!--对象字段里也可以进行结果映射--> </association> <!--如果属性是集合,一般需要通过某个列名再去查询到该集合(一对多查询)--> <collection property="对象属性名" column="映射集合的列名" javaType="集合类型" ofType="集合泛型类型" select="连接查询的id"> <result column="数据库列名" property="类属性名"/><!--集合字段里也可以进行结果映射--> </collection> </resultMap>
使用方法(resultMap="结果集映射的id"):
<select id="getUserList" resultMap="name"> select * from jdbcstudy.student; </select>
logImpl
指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING
COMMONS_LOGGING | STDOUT_LOGGING
NO_LOGGING
设置方式(设置标准日志STDOUT_LOGGING)
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
日志打印
导入log4j
<!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
配置log4j:log4j.properties(下面是一个简单的配置)
# set log levels log4j.rootLogger=DEBUG,console,file # 输出到控制台 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.Threshold=DEBUG log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=【%c】-%m%n # 文件输出的相关设置 log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=./log/leye.log log4j.appender.file.MaxFileSize=10mb log4j.appender.file.Threshold=DEBUG log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n # 日志输出级别 log4j.logger.org.mybatis=DEBUG log4j.logger.java.sql=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.ResultSet=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
使用:Logger logger = Logger.getLogger(class);
limit分页,使用了map之后可以传多个参数
<select id="getUserList" parameterType="map" resultType="pojo.User"> select * from jdbcstudy.student limit #{startpage},#{num}; </select>
将sql语句直接注解到接口抽象方法里,比如一个简单的查询语句
@Select("select * from student") List<User> getUserList();//无参查询
但是,注解注入的方式只适用于少数sql语句比较简单的情况,值得一提的是,在对于多个基本类型参数sql方法,必须要在参数前再加一个指名注解
User getUserBy(@Param("id") int id ,@Param("name") String name);
之前是用map解决的,但对于只有少数参数的sql语句,用map就有点大材小用,这里用注解更加方便,但只针对于用注解注入sql语句的情况
@Select("select * from student") @Results(id = "userMap",value = { @Result(column = "id" ,property = "anInt") }) List<User> getUserList();//无参查询
设置id是为了方便其他的结果映射注解去调用,如
@Select("select * from student where id=#{id}") @ResultMap(value = "userMap") User getUserById(int id);//根据id查询用户
<select id="" parameterType="" resultType=""> select * from student where 1=1<!--方便拼接字符串--> <if test="表达式"> and sql语句<!--表达式成立的话,拼接该字符串--> </if> </select>
一般为了在if等标签里拼接字符串,前面都得模拟一个true的where语句
<select id="" ..> select * from student where 1=1 <if>...</if> </select>
这样虽然可行,但却降低了耦合性
jsp标签提供了一个where标签来解决这种问题
注意:在第二条语句之后都要加上and
<select id="" ..> select * from student <where> <if test="">...</if> <if test="">and...</if> </where> </select>
类似于java的swicth
<choose> <when test="表达式"> and 拼接sql </when> ... <otherwise> .. </otherwise> </choose>
set语句可以自动联系sql语句中的 ‘,‘逗号,发现多余的逗号会帮你去掉,和where标签的and比较像,多用于像修改、插入这种含,的sql语句
<set> <if test="">...,</if> <if test="">...,</if> <if test="">...,</if> </ set>
像where、set标签都可以通过trim标签去定制
<trim prefix="where" prefixOverrides="AND|OR">//自动覆盖and、or前缀 //定制where语句 </trim> <trim prefix="set" suffixOverrides=",">//自动覆盖,后缀 //定制set语句 </trim>
可以将某些sql的公共部分提取出来,以便复用
//sql片段定义 <sql id="sqlName"> ... </sql> //sql片段使用 <include refid="sqlName"></include>
可以遍历取出list里的元素拼接sql语句
<foreach collection="listName" item="elemName" open="" close="" separator=""> ... </foreach> //其中collection是要从中取出元素的集合,item是每个元素的引用名称, open、close分别是拼接sql的开始和结束,sepqarator是拼接sql的间隔符 比如要拼接一个(1,2,3,4)的sql <foreach collection="listName" item="id" open="(" close=")" separator=","> #{id} </foreach>
MyBatis默认定义了二级缓存:一级缓存和二级缓存
<setting name="cacheEnabled" value="true">//开启缓存
一级缓存:SqlSession级别的缓存,也就是本地缓存,增删改查和不同查询等会自动清除缓存
二级缓存:基于namespace的缓存,需要手动开启配置,它可以将对话框关闭后存在一级缓存中的数据存到mapper对应的二级缓存中
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" >
//创建了一个每60s刷新的FIFO缓存,最多可以存储512个引用,而且返回只读对象
标签:ref private block 事务管理 resources 字母 本地 false when
原文地址:https://www.cnblogs.com/wtlbbdbk/p/14839443.html