官方文档:https://mybatis.org/mybatis-3/zh/index.html
持久层解释
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/student?useSSL=true&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
</configuration>
public class mybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//1.获取sqlsessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//2.可以执行crud的对象
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
实体类
//实体类
public class user {
private int id;
private String username;
private String pwd;
public user() {
}
public user(int id, String username, String pwd) {
this.id = id;
this.username = username;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "user{" +
"id=" + id +
", username=‘" + username + ‘\‘‘ +
", pwd=‘" + pwd + ‘\‘‘ +
‘}‘;
}
}
接口
public interface userDao {
List<user> getUserList();
}
设置对应的mapping配置文件
<?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绑定一个对应的接口-->
<mapper namespace="com.sun.dao.userDao">
<!--select查询语句-->
<select id="getUserList" resultType="com.sun.pojo.user">
select * from student.user
</select>
</mapper>
编写一个测试类
public class UserDao_Test {
@Test
public void test(){
SqlSession sqlSession= mybatisUtils.getSqlSession();
UserDao userDao=sqlSession.getMapper(UserDao.class);
List<User> userList=userDao.getUserList();
for(User user : userList)
{
System.out.println(user);
}
}
}
注册mapping
<mappers>
<mapper resource="com/sun/dao/UserMapper.xml"></mapper>
</mappers>
处理找不到文件的问题
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
namespace
namespace中的包名要和mapper接口的包名一致
select
步骤:
编写接口
List<User> getUserList();
编写对应的mapper中的sql语句
<select id="getUserList" resultType="com.sun.pojo.User">
select * from student.user
</select>
测试
@Test
public void test(){
//第一步,获得sqlSession对象
SqlSession sqlSession= mybatisUtils.getSqlSession();
try {
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
List<User> userList= userMapper.getUserList();
for(User user : userList)
{
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭sqlSession
sqlSession.close();
}
}
注意:增删改需要 提交事务!
<select id="getUserbyId" resultType="com.sun.pojo.User" parameterType="int">
select * from student.user where id=#{id}
</select>
<select id="insertUser" parameterType="com.sun.pojo.User">
insert into student.user (id,username ,pwd) values (#{id},#{username},#{pwd})
</select>
<update id="updateUser" parameterType="com.sun.pojo.User">
update student.user set username=#{username},pwd=#{pwd} where id=#{id};
</update>
<delete id="deletebyId" parameterType="int">
delete from student.user where id=#{id}
</delete>
map传递参数,直接在SQL中取出key即可!
parameterType="map"
对象传递参数,直接在SQL中取对象的属性即可 !
parameterType="com.sun.pojo.User">
只有一个基本类型参数的情况下,可以直接在SQL中取到!
多个参数用map或注解!
1 可以用db.properties方法来优化
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/student?useSSL=true&useUnicode=true
username=root
password=123
<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>
2 优先级问题
如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。
类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余
第一种:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
第二种:
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
在实体类比较少的时候,使用第一类;
如果实体类十分多,建议使用第二类;
第一章可以DIY(自定义),第二种则不行,如果非要改,可以在实体中增加注解
注册绑定xml
每一个Mapper.xml都必须在Mybatis的核心配置文件下进行注册
方法一:通过xml【推荐使用】
<mappers>
<mapper resource="com/sun/dao/UserMapper.xml"></mapper>
</mappers>
方式二:使用class文件注册
<mappers>
<mapper class="com.sun.dao.UserMapper"></mapper>
</mappers>
注意:
方法三:
<mappers>
<package name="com.sun.dao"/>
</mappers>
注意:
作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。
这里的每一个Mapper都代表一个具体的业务!
原来这样的sql语句
select * from student.user where id=#{id}
如果直接执行,就会出现错误,对应的属性值可能为空
改成这样即可,起别名
select id,username,pwd as password from student.user where id=#{id}
id,username,pwd就是数据库中的字段名
password是pwd对应的属性名
id username pwd 数据库中的字段名
id username password 对应的属性名
日志工厂
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手!
注意:value后面小心空格!
LOG4j
导入jar包
配置log4j.properties (新建以这个为名)这个配置文件
配置log4j为日志的实现
<settings>
<setting name="logImpl" value="LOG4j"/>
</settings>
测试
接口
List<User> getUserbyLimit(Map<String,Object> map);
Mapper.xml
<select id="getUserbyLimit" parameterType="map" resultType="com.sun.pojo.User">
select * from student.user limit #{startIndex},#{pageslll}
</select>
测试
@Test
public void getUserbyLimit(){
SqlSession sqlSession = null;
try {
sqlSession= mybatisUtils.getSqlSession();
UserMapper mapper= sqlSession.getMapper(UserMapper.class);
Map<String,Object> map=new HashMap<String, Object>();
map.put("startIndex",0);
map.put("pageslll",2);
List<User> userList= mapper.getUserbyLimit(map);
for (User user : userList) {
System.out.println(user);
}
;
} catch (Exception e) {
e.printStackTrace();
}
sqlSession.close();
}
本质:反射机制体现!
底层:动态代理!
接口实现
//方法存在多个参数,一定要用@Param,方法中的参数和@Param中的参数相比,以@Param中的参数为主
@Select("select * from user where id=#{id}")
User getiUserID(@Param("id") int id);
核心配置文件绑定接口
<mappers>
<mapper class="com.sun.dao.UserMapper"></mapper>
</mappers>
测试
//注解开发
@Test
public void getiUserID(){
SqlSession sqlSession=mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
User user=mapper.getiUserID(1);
System.out.println(user);
sqlSession.close();
}
接口实现
@Insert("insert into user(id,username,pwd) values(#{id},#{username},#{pwd})")
int insertUserBy(User user);
如查询的步骤二一样,绑定过一次就不用每次都绑定了!
测试
@Test
public void insertUserBy(){
SqlSession sqlSession=mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
mapper.insertUserBy(new User(22,"李红","890"));
sqlSession.close();
}
注意:正常情况下,增删改都需要提交事务才能够真正修改数据库!现在不用,是因为设置了自动提交事务!
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession(true);
}
接口实现
@Update("update user set username=#{username},pwd=#{pwd} where id=#{id}")
int updateByzhujie(User user);
如查询的步骤二一样,绑定过一次就不用每次都绑定了!
测试
@Test
public void insertUserBy(){
SqlSession sqlSession=mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
mapper.updateByzhujie(new User(9,"时代","457"));
sqlSession.close();
}
接口实现
@Delete("delete from user where id=#{id}")
int deleteByzhujie(int id);
如查询的步骤二一样,绑定过一次就不用每次都绑定了!
测试
@Test
public void insertUserBy(){
SqlSession sqlSession=mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
mapper.deleteByzhujie(22);
sqlSession.close();
}
目的是为了简化开发,它是个java库,是个构建工具,也是个插件
idea中加入插件
在项目中导入jar包
在实体类中加注解即可
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
Code inspections
Refactoring actions (lombok and delombok)
多个学生,一个老师
环境搭建
实体类
定义:自动生成SQL语句
<select id="queryByIF" resultType="com.sun.pojo.User" parameterType="map">
select * from student.user where 1=1
<if test="id!=null">
and id=#{id}
</if>
</select>
注意:resultType中应该写成com.sun.pojo.User,而不是简单的User就可以了!
<select id="queryByIF" resultType="com.sun.pojo.User" parameterType="map">
select * from student.user
<where>
<if test="id!=null">
and id=#{id}
</if>
</where>
</select>
注意:where主要是可以自动添加或删除and,可以一个条件成立,也可以多个条件成立
set 的作用就是只能选择一个条件成立
trim:定制 where 元素的功能
注意事项:
经常查询但是不经常改变的数据
Mybatis中默认有两个缓存,一级缓存和二级缓存
测试步骤:
开启日志
测试在一个session中查询两次相同记录
查看日志,分析
通过id查询两次id=1的数据
**通过查看日志可以看出SQL·语句执行了一次,第二次直接从缓冲中获取了
查看id=1和id=2的数据
可以发现,SQL语句执行了两次!因为这是不同的数据,查询过id=1的数据之后,缓存中并没有id=2的数据,因此需要再次查询数据库
缓存失效:
小结:一次缓存默认是开启的,只在一次sqlsession中有效,也就是拿到连接到关闭连接的区间段!一级缓存就是一个mapper!
步骤:
显示开启全局缓存( 默认就是开启的,现在只是显示出来而已)
<settings>
<!-- 显示的开启全局缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
在一个mapper中开启二级缓存
<!-- 在当前maper中开启二级缓存-->
<cache/>
也可以自定义参数
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
测试
问题是我们需要将实体类序列化!否则就会报错!
改为
小结:
缓存顺序:
ehcache是一种广泛使用的开源java分布式缓存,主要用于通用缓存
要在程序中使用
原文:https://www.cnblogs.com/shyshare/p/14553529.html