maven
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency>
github
https://github.com/mybatis/mybatis-3.git
中文文档
https://github.com/mybatis/mybatis-3.git
为什么需要持久化?
Dao层,Service层,Controller层
CREATE DATABASE `mybatis` USE `mybatis` DROP TABLE IF EXISTS `user`; CREATE TABLE `user`( `id` INT(20) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `pwd` VARCHAR(10), PRIMARY KEY(`id`) )ENGINE = INNODB CHARSET=utf8
创建父工程mybatis-study,创建子工程mybatis-01,在父工程中添加依赖
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</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>
编写配置文件
<?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=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
package com.hopeful.utils; 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; /** * MyBatisUtils * * @author : yl * @version : [v1.0] * @createTime : [2021/7/15 7:24] */ public class MyBatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = null; inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } private static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
package com.hopeful.pojo; /** * User * * @author : yl * @version : [v1.0] * @createTime : [2021/7/15 7:30] */ public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } 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; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
package com.hopeful.dao; import com.hopeful.pojo.User; import java.util.List; public interface UserDao { List<User> getUserList(); }
<?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 namespace="com.hopeful.dao.UserDao"> <!-- resultType 返回类型,集合的话指定集合中反省的类型--> <select id="getUserList" resultType="com.hopeful.pojo.User"> select * from mybatis.user; </select> </mapper>
可能出现的问题
解决方案,配置资源的路径,因为默认加载resource的特定目录
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
所有java或resource文件夹下的xml/properties文件无法加载
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
数据库连接失败,出现Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
解决方案:
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
mapper配置文件
<property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
pom.xml文件
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency>
测试
// 方法一 推荐使用方法一 @Test public void testSelectList() { SqlSession sqlSession = null; try { sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } }catch (Exception e) { System.out.println(e.getMessage()); }finally { sqlSession.close(); } } // 方法二 @Test public void testOne() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); List<User> users = sqlSession.selectList("com.hopeful.dao.UserMapper.getUserList"); for (User user : users) { System.out.println(user); } }
namespace,顾名思义就是命名空间,需要指定接口文件(mapper)的全限定类名,接口名称和namespace路径中的接口名称需完全一致
<!-- namespace 命名空间 指定dao接口的路径 --> <mapper namespace="com.hopeful.dao.UserMapper">
命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。
**命名解析:**为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
/*** * 获取用户列表 * @return */ List<User> getUserList();
<select id="getUserList" resultType="com.hopeful.pojo.User"> select * from user; </select>
@Test public void testSelectList() { // try{}catch(){}finally{} 官网推荐写法 SqlSession sqlSession = null; try { sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } }catch (Exception e) { System.out.println(e.getMessage()); }finally { sqlSession.close(); } }
/** * 新增用户 * @param user * @return */ int insertUser(User user);
<insert id="insertUser" parameterType="com.hopeful.pojo.User"> insert into user(id,name,pwd) value (#{id},#{name},#{pwd}) </insert>
@Test public void insertUser() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int count = mapper.insertUser(new User(4, "晨晨", "123123")); if(count > 0) { System.out.println("插入成功"); } // 提交事务 sqlSession.commit(); // sqlSession.commit(true); sqlSession.close(); }
mapper(userMapper.java)接口文件
<update id="updateUserById" parameterType="com.hopeful.pojo.User"> update user set name=#{name},pwd=#{pwd} where id = #{id}; </update>
其它可参考上方写法。
mapper(userMapper.java)接口文件
<delete id="deleteUserById" parameterType="int"> delete from user where id = #{id} </delete>
其它可参考上方写法。
sqlSession.close();
// 提交事务 sqlSession.commit();
mapper接口文件
/** * 新增用户 * @param user * @return */ int insertUserByMap(HashMap<String,Object> user);
mapper.xml文件
<insert id="insertUserByMap" parameterType="map"> insert into user(id,name,pwd) value (#{id},#{username},#{password}) </insert>
测试代码
@Test public void insertUserByMap() { SqlSession sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("id",5); map.put("username","狂神"); map.put("password","666666"); int count = mapper.insertUserByMap(map); if(count > 0) { System.out.println("插入成功"); } // 提交事务 sqlSession.commit(); // sqlSession.commit(true); sqlSession.close(); }
总结:
mapper.java文件
List<User> getUserList2(String value);
java 代码执行的时候,传递通配符%%
mapper.xml文件
select * from user where name like #{value}
测试代码
List<User> userList2 = mapper.getUserList2("%狂%");
在sql拼接中使用通配符
mapper.xml文件
select * from user where name like "%"#{value}"%"
测试代码
List<User> userList2 = mapper.getUserList2("狂");
mybatis核心配置文件为mybatis-config.xml(也可以为其它名称)
configuration(配置)
db.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8 username=root password=root
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> <!-- url:http://localhost:8080/mybatisserver/dome1Servlet --> <!-- file://${filePath} --> <properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="root"/> </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> <mappers> <mapper resource="com/hopeful/dao/UserMapper.xml"/> </mappers> </configuration>
注意:
可以直接引入配置文件
mybatis-config 配置加载
首先读取在 properties 元素体内指定的属性。
然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
配置文件属性的优先级高于properties标签中子元素的属性值。即properties子元素中填写错误连接信息,而配置文件填写正确信息,仍可连接,反之无法连接。
mybatis-config 中configuration标签内的子标签必须按照顺序书写,即properties,…environment,…mapper等顺序
properties中 url 和 resources 的区别
<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 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
连接数据库 dbcp c3p0 druid
<mappers> <!-- 常用 1.使用xml文件注册 从项目根路径查找 --> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <!-- 不用 2.使用xml文件注册 通过文件协议查找--> <mapper url="file:///var/mappers/BlogMapper.xml"/> <!-- 2.使用class文件绑定注册 接口与配置文件必须同名,且在同一路径下 否则,报错,Invalid bound statement (not found)--> <mapper class="org.mybatis.builder.BlogMapper"/> <!-- 3.使用扫描包进行注册 接口与配置文件必须同名,且在同一路径下 --> <package name="org.msaybatis.builder"/> </mappers>
类型别名,可以缩短全限定类名的书写。
<!-- mybatis-config.xml --> <typeAliases> <typeAlias type="com.hopeful.pojo.User" alias="User"/> </typeAliases>
<!-- resultType使用的别名不区分大小写,即User或user都可以,但建议和别名一致 --> <select id="getUserList" resultType="user"> select * from user; </select>
com.hopeful.pojo.User
的别名为 user
;若有注解,则别名为其注解值。<typeAliases> <package name="com.hopeful.pojo"/> </typeAliases>
<!-- resultType使用的别名不区分大小写,即User或user都可以,但建议按照官网约定,使用小写,这样一看就知道是包名指定 --> <select id="getUserList" resultType="User"> select * from user; </select>
如果实体类少,可以使用第一种(指定实体类的方法)
如果实体类多,建议使用第二种(指定报名的方法),如果需要修改别名,需要通过注解
@Alias("UserAlias") public class User {}
<select id="getUserList" resultType="UserAlias"> select * from user; </select>
常见的 Java 类型内建的类型别名
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
常用的设置
问题:当属性值和数据库字段不一样时,有两种解决方案
<select id="selectUsers" resultType="User"> select user_id as "id", user_name as "userName", hashed_password as "hashedPassword" from some_table where id = #{id} </select>
<resultMap id="userResultMap" type="User"> <id property="id" column="user_id" /> <result property="username" column="user_name"/> <result property="password" column="hashed_password"/> </resultMap> <select id="selectUsers" resultMap="userResultMap"> select user_id, user_name, hashed_password from some_table where id = #{id} </select>
resultMap
resultMap
元素是 MyBatis 中最重要最强大的元素。ResultMap
的优秀之处——你完全可以不用显式地配置它们。属性名和字段名不一致进行配置,一致的话可以不配置[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8KYKHxmo-1642922986891)(C:\Users\Apple\Desktop\笔记\Mybatis.assets\image-20210727073432156.png)]
<!-- mybatis-config.xml文件 在properties后面,typeAliases前面 --> <settings> <!-- 标准日志 --> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
添加依赖
<!-- 日志框架 --> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 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/shun.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
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
测试代码查看日志
package com.hopeful.dao; import com.hopeful.pojo.User; import com.hopeful.utls.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.apache.log4j.Logger; import org.junit.Test; import java.util.List; /** * testUserDao * * @author : yl * @version : [v1.0] * @createTime : [2021/7/16 22:07] */ public class testUserDao { static Logger logger = Logger.getLogger(testUserDao.class); @Test public void testLog4j() { logger.info("info: 进入了testLog4j方法"); logger.debug("info: 进入了testLog4j方法"); logger.error("info: 进入了testLog4j方法"); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wujlsw60-1642922986895)(C:\Users\Apple\Desktop\笔记\Mybatis.assets\image-20210727214924449.png)]
方案一:
file -> setting -> Editor -> fileType -> text添加.log文件
如果还是不行,建议查看mybatis-config.xml的类型别名不要使用包扫描
<typeAliases> <typeAlias type="com.hopeful.pojo.User" alias="User"/> </typeAliases>
select * from user limit startIndex,pageSize; select * from user 3; [0,3]
添加接口方法
List<User> getUserListByLimit(Map<String,Integer> map);
添加userMapper.xml文件
<select id="getUserListByLimit" parameterType="map" resultMap="userMap" > select * from user limit #{startIndex},#{pageSize}; </select>
测试
@Test public void testSelectByLimit() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Integer> map = new HashMap<String, Integer>(); map.put("startIndex",3); map.put("pageSize",3); List<User> userList = mapper.getUserListByLimit(map); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
userMapper.java
List<User> getUserListByRowBounds();
userMapper.xml
<resultMap id="userMap" type="User"> <result property="password" column="pwd"/> </resultMap> <select id="getUserListByLimit" parameterType="map" resultMap="userMap" > select * from user limit #{startIndex},#{pageSize}; </select> <select id="getUserListByRowBounds" resultMap="userMap"> select * from user; </select>
测试
static Logger logger = Logger.getLogger(testUserDao.class); @Test public void testSelectByLimit() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Integer> map = new HashMap<String, Integer>(); map.put("startIndex",3); map.put("pageSize",3); List<User> userList = mapper.getUserListByLimit(map); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
官网:https://pagehelper.github.io/
p15:
大家之前都学过
另一种方法来完成语句映射,而可以使用 Java 注解来配置。
@Select("select * from user") List<User> getUserList();
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eWEO39zV-1642922986896)(\Mybatis.assets\mybatis启动流程.png)]
userMapper.java
@Insert("insert into user(id, name, pwd) value(#{id},#{name},#{password})") int insertUser(@Param("id") int id, @Param("name") String name, @Param("password") String password); @Update("update user set name = #{name}, pwd = #{password} where id = #{id}") int updateUser(@Param("id") int id, @Param("name") String name, @Param("password") String password); @Delete("delete from user where id = #{uid}") int deleteById(@Param("uid") int id);
测试
@Test public void testGetUserById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.getUserById(2); System.out.println(user); sqlSession.close(); } @Test public void testInsertUser() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.insertUser(10,"Hopeful","123567"); sqlSession.close(); } @Test public void testUpdateUser() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.updateUser(10,"晨晨","abcef"); sqlSession.close(); } @Test public void testDeleteById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.deleteById(10); sqlSession.close(); }
该注解用于标识参数
如果基本数据类型或String类型,可用@Param注解
引用类型不用该注解(实体类,或map)
多个基本类型或String类型参数,需用@Param注解
一个基本类型或String类型参数,建议使用@Param注解(虽然不使用也可以)
如果使用该注解后,sql语句中的参数名称应该使用注解标记的属性名称
Lombok 是一个很方便的插件,本质是个 Java 库,使用它通过相关注解就可以不用再编写冗长的 getter 或者 equals 等方法了。
Lombok 注解思维导图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AkiJBSfl-1642922986897)([外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yqkGFrwv-1642922990809)(\Mybatis.assets\lombok.jpg)]]
点击 File->Settings->Plugins,搜索 Lombok
,然后点击安装 Lombok 插件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fS8wjjuj-1642922986897)(Mybatis.assets/image-20210730131237530.png)]
首先在 pom 文件中引入依赖:
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> </dependencies>
<!-- 创建表 --> CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO teacher(`id`, `name`) VALUES (1, 秦老师); CREATE TABLE `student` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, 小明, 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, 小红, 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, 小张, 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, 小李, 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, 小王, 1);
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8 username=root password=root
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> <!-- url:http://localhost:8080/mybatisserver/dome1Servlet --> <!-- file:${filePath} --> <properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="root2"/> </properties> <settings> <!-- 标准日志 --> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <typeAliases> <!-- <typeAlias type="com.hopeful.pojo.User" alias="User"/>--> <!-- <package name="com.hopeful.pojo"/>--> </typeAliases> <environments default="development"> <environment id="test"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> <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> <mappers> <mapper class="com.hopeful.dao.StudentMapper"></mapper> <mapper class="com.hopeful.dao.TeacherMapper"></mapper> </mappers> </configuration>
mybatisUtils
package com.hopeful.utils; 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; /** * MybatisUtils * * @author : yl * @version : [v1.0] * @createTime : [2021/7/16 22:00] */ public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory = null; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
Student.java
package com.hopeful.pojo; import lombok.Data; /** * Student * * @author : yl * @version : [v1.0] * @createTime : [2021/8/1 6:47] */ @Data public class Student { private int id; private String name; private Teacher teacher; }
Teacher.java
package com.hopeful.pojo; /** * Teacher * * @author : yl * @version : [v1.0] * @createTime : [2021/8/1 6:49] */ public class Teacher { private int id; private String name; }
StudentMapper
package com.hopeful.dao; /** * StudentMapper * * @author : yl * @version : [v1.0] * @createTime : [2021/8/1 6:50] */ public interface StudentMapper { }
TeacherMapper
package com.hopeful.dao; import com.hopeful.pojo.Teacher; import org.apache.ibatis.annotations.Select; public interface TeacherMapper { @Select("select * from teacher") public Teacher getTeacherById(int id); }
Mytest
package com.hopeful.dao; import com.hopeful.pojo.Teacher; import com.hopeful.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; /** * TestEnv * * @author : yl * @version : [v1.0] * @createTime : [2021/8/1 6:56] */ public class MyTest { @Test public void testEnv() { SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacherById(1); System.out.println(teacher); } }
出现查询结果,证明环境没问题!
<select id="getStudentTeacherList" resultMap="studentTeacher"> select * from student; </select> <resultMap id="studentTeacher" type="student"> <result property="id" column="id"></result> <result property="name" column="name"></result> <association property="teacher" javaType="Teacher" column="tid" select="com.hopeful.dao.TeacherMapper.getTeacherById"></association> </resultMap> <select id="getTeacherById" resultType="Teacher"> select * from teacher where id = #{tid} </select>
<select id="getStudentTeacherList2" resultMap="studentTeacher2"> select s.id sid, s.name sname, t.id tid,t.name tName from student s,teacher t where s.tid = t.id </select> <resultMap id="studentTeacher2" type="student"> <result property="id" column="sid"></result> <result property="name" column="sname"></result> <association property="teacher" javaType="teacher"> <result property="id" column="tid"></result> <result property="name" column="tName"></result> </association> </resultMap>
@Test public void testGetStudent2() { SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // List<Student> list = mapper.getStudentTeacherList(); List<Student> list = mapper.getStudentTeacherList2(); for (Student student : list) { System.out.println(student); } sqlSession.close(); }
总结:
环境搭建,同上
<!-- 连表查询 --> <select id="selectTeacheList" resultMap="teacherStudent" > select t.id tid, t.name tName, s.id sid, s.name sName from teacher t, student s where s.tid = t.id </select> <resultMap id="teacherStudent" type="teacher"> <result property="id" column="tid"></result> <result property="name" column="tName"></result> <collection property="students" ofType="student"> <result property="id" column="sid"></result> <result property="name" column="sName"></result> </collection> </resultMap>
<select id="selectTeacheList2" resultMap="teacherStudent2"> select * from teacher; </select> <resultMap id="teacherStudent2" type="teacher"> <!-- 此处因集合子元素(student)也有id 故需要显示书写--> <result property="id" column="id"></result> <!-- java类型 ofType可省略 --> <collection property="students" javaType="list" ofType="student" select="selectStudentByTid" column="id" > </collection> </resultMap> <select id="selectStudentByTid" resultType="student"> select * from student where tid = #{tid} </select>
嵌套查询 sql简单,映射复杂,不易调试
连表查询 sql复杂,映射简单,因sql书写完成,容易调试(推荐)
association - 关联 - 多对一
collection - 集合 - 一对多
javaType 实体类中的属性类型(如List)
ofType 集合中实体类 的类型
面试高频:
所谓动态SQL,本质上还是SQL语句,只是它会根据条件的不同,而拼接不同的SQL语句。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
准备表
CREATE TABLE `blog`( `id` VARCHAR(50) NOT NULL COMMENT '博客id', `title` VARCHAR(100) NOT NULL COMMENT '博客标题', `author` VARCHAR(30) NOT NULL COMMENT '博客作者', `create_time` DATETIME NOT NULL COMMENT '创建时间', `views` INT(30) NOT NULL COMMENT '浏览量' )ENGINE=INNODB DEFAULT CHARSET=utf8;`mybatis`
创建一个基础工程(子项目)
创建module,并导包
编写配置文件(可参考上面环境搭建)
编辑工具类
public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory = null; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
public class IDUtils { public static String getUUID() { return UUID.randomUUID().toString().replace("-",""); } }
编辑实体类对象
@Data public class Blog { private String id; private String title; private String author; private Date createTime; private int views; }
int insertBlog(Blog blog);
<insert id="insertBlog" parameterType="blog"> insert into blog(id, title, author, create_time, views) values (#{id}, #{title}, #{author}, #{createTime}, #{views}) </insert>
@Test public void testInsert() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(); blog.setId(IDUtils.getUUID()); blog.setTitle("Mybatis"); blog.setAuthor("Hopeful"); blog.setCreateTime(new Date()); blog.setViews(1200); mapper.insertBlog(blog); blog.setId(IDUtils.getUUID()); blog.setAuthor("狂神说"); blog.setTitle("Spring"); blog.setCreateTime(new Date()); blog.setViews(1000); mapper.insertBlog(blog); blog.setId(IDUtils.getUUID()); blog.setTitle("Mybatis"); blog.setAuthor("小菜鸟"); blog.setCreateTime(new Date()); blog.setViews(9000); mapper.insertBlog(blog); sqlSession.close(); }
List<Blog> queryBlogByIF(HashMap map);
<select id="queryBlogByIF" parameterType="map" resultType="blog"> select * from blog <where> <if test="title != null"> and title like concat('%',#{title},'%') </if> <if test="author != null"> and author like concat('%',#{author},'%') </if> </where> </select>
使用技巧:
果参数为数字类型的时候没有特俗需求的情况只需要判断是否为null即可。
<if test="id != null"></if>
如果有特俗需求,例如判断是否大于某个数的时候才行。只需要加上对应的条件判断即可
<if test='id != null and id > 28'></if>
特殊符号转义
转义符 | 对应符号 |
---|---|
> | > |
< | < |
>e; | >= |
<e; | <= |
如果为字符串类型
如果需要过滤空串,添加空串判断即可 不支持 && 所以这里用 and or || 来做逻辑与或的判断
<if test="username != null and '' != username"></if> <!-- 或者 --> <if test="username != null and '' neq username"></if>
如果判断字符串是否已某个特俗字符开头,结尾等。直接调用String的对应方法即可
<if test="username != null and username.indexOf('ji') == 0"> </if> <!-- 是否以什么开头 --> <if test="username != null and username.indexOf('ji') >= 0"> </if> <!-- 是否包含某字符 --> <if test="username != null and username.lastIndexOf('ji') > 0"></if> <!-- 是否以什么结尾 -->
注意:
<if test="username != null and 'hello' == username"></if>
这种形式的写法在参数类型是字符串的时候是没有问题的,
但是参数类型为非字符串类型的时候就需要写成<if test="username != null and 'hello'.toString() == username.toString()"></if>
仅仅写成<if test="username != null and 'hello'.toString() == username"></if>
也会有很大可能会挂。
上面说过,if条件判断可以直接调用对象自身的方法进行逻辑判断,所以list判空。可以调用.size()>0或者.isEmpty()
<if test="userList != null and userList.isEmpty()"></if> <if test="userList != null and userList.size()>0"></if>
@Test public void testqueryBlogByIF() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, String> map = new HashMap<String, String>(); // map.put("title","Spring"); // map.put("author","狂神说"); List<Blog> blogs = mapper.queryBlogByIF(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
List<Blog> queryBlogByChoose(HashMap map);
<select id="queryBlogByChoose" parameterType="map" resultType="blog"> select * from blog <where> <choose> <when test="title != null"> and title like concat('%', #{title},'%') </when> <when test="author != null"> and author like concat('%', #{author},'%') </when> <otherwise> and views = 9999 </otherwise> </choose> </where> </select>
@Test public void testqueryBlogByChoose() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("title","Spring"); map.put("author","Hopeful"); map.put("views",1000); List<Blog> blogs = mapper.queryBlogByChoose(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
int updateBlogBySet(HashMap map);
<!-- set 存在一个问题,就是当所有条件都不满足时会出现sql语法错误--> <update id="updateBlogBySet" parameterType="map"> update blog <set> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author}, </if> </set> where id = #{id} </update>
// 条件都不满足时 会出现sql语法错误 @Test public void testupdateBlogBySet() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); // map.put("title","java如此简单"); // map.put("author","小菜鸟"); // map.put("id","86120dda6b3e45a6a06202895cd2b459"); mapper.updateBlogBySet(map); sqlSession.close(); }
所谓SQL片段,就是将sql中重复的部分抽取出来,通过在需要的地方进行引用,以达到复用的目的。
<sql id="if-title-author"> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author}, </if> </sql> <!-- set 存在一个问题,就是当所有条件都不满足时会出现sql语法错误--> <update id="updateBlogBySet" parameterType="map"> update blog <set> <include refid="if-title-author"></include> </set> where id = #{id} </update>
测试代码,如上。
所谓的动态SQL,本质上还是SQL,只是在SQL代码的基础上,添加一些逻辑代码。
BlogMapper.java
List<Blog> queryBlogByForeach(HashMap map);
BlogMapper.xml
<select id="queryBlogByForeach" parameterType="map" resultType="blog"> select * from blog <where> <if test="ids != null"> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id = #{id} </foreach> </if> </where> </select>
测试
@Test public void testqueryBlogByForeach() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); ArrayList<String> ids = new ArrayList<String>(); ids.add("86120dda6b3e45a6a06202895cd2b459"); ids.add("b757564a6b374eb9b4c6d2cf96b86d21"); ids.add("187be67b9340405e81daa31886501173"); map.put("ids",ids); mapper.queryBlogByForeach(map); sqlSession.close(); }
总结
动态SQL,其实就是在拼接SQL语句,只要保证SQL语句语法的合法性,进行排列组合就好了
查询数据时,需要连接数据库,比较消耗资源,为了提高查询效率,需要将查询的数据存放到一个可以提取的地方 (内存),当再次查询相同的数据时,不用连接数据库直接取出内存中的数据,缓解数据库压力,提升查询效率。
Mybatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存,缓存可以极大地提高查询的效率。
Mybatis系统中默认定义了两级缓存,一级的缓存和二级缓存。
默认情况下,只有一级缓存开启(sqlSession级别的缓存,也成为本地缓存)
代码演示:
User queryUserById(int id);
<select id="queryUserById" parameterType="_int" resultType="user"> select * from mybatis.user where id = #{id} </select>
@Test public void testQueryUserById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); // mapper.updateUser(new User(1,"Hopeful","abc")); // User user2 = mapper.queryUserById(3); // 关闭缓存,第二次查询相同的数据还会查询数据库 sqlSession.clearCache(); User user2 = mapper.queryUserById(1); System.out.println(user2); sqlSession.close(); }
注意点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ShnjIrH-1642922986898)(Mybatis.assets/image-20210902063606063.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S2G4DPf8-1642922986898)(Mybatis.assets/image-20210902063632833.png)]
数据库查询一次!
缓存失效
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0bmBCl8w-1642922986899)(Mybatis.assets/image-20210902063746094.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJXHzQDB-1642922986900)(Mybatis.assets/image-20210902063823939.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BzgHpyxF-1642922986901)(Mybatis.assets/image-20210902063923688.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b8VtF3gy-1642922986901)(Mybatis.assets/image-20210902064007039.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tk3niOPV-1642922986901)(Mybatis.assets/image-20210902064118100.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wJ9gAw6K-1642922986902)(Mybatis.assets/image-20210902064148444.png)]
一级缓存就是一个Map。
开启二级缓存的步骤:
在mybatis-config.xml文件中显示开启二级缓存
<!-- mybatis-config.xml --> <!-- 显示地开启全局缓存(二级缓存)--> <setting name="cacheEnabled" value="true"/>
在userMapper.xml文件中添加标签
<cache/>
也可以根据需求定义一些属性
<cache eviction="FIFO" flushInterval="60000" <!-- size为正整数,设置0无效 --> size="512" readOnly="true"/>
测试
实体类进行序列化。
问题:
如果实体类,没有序列化,需要序列化,否则可能会报实体类没有序列化的错误。
如:Error serializing object. Cause: java.io.NotSerializableException: com.hopeful.pojo.User
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGVyK2yC-1642922986902)(Mybatis.assets/image-20210902072639504.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iOcPbYGh-1642922986902)(Mybatis.assets/image-20210902072715425.png)]
两个sqlSession中调用统一mapper中的查询语句,只查询一次数据库,证明二级缓存已经生效(因为一级缓存基于SqlSession的)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ntf28TV5-1642922986903)(Mybatis.assets/image-20210903071431640.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HPTbNwUB-1642922986904)(Mybatis.assets/image-20210903072015269.png)]
CREATE TABLE `smbms_address` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `contact` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人姓名', `addressDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '收货地址明细', `postCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '邮编', `tel` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人电话', `createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者', `creationDate` DATETIME DEFAULT NULL COMMENT '创建时间', `modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者', `modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间', `userId` BIGINT(20) DEFAULT NULL COMMENT '用户ID', PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE `smbms_bill` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `billCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '账单编码', `productName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品名称', `productDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品描述', `productUnit` VARCHAR(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品单位', `productCount` DECIMAL(20,2) DEFAULT NULL COMMENT '商品数量', `totalPrice` DECIMAL(20,2) DEFAULT NULL COMMENT '商品总额', `isPayment` INT(10) DEFAULT NULL COMMENT '是否支付(1:未支付 2:已支付)', `createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)', `creationDate` DATETIME DEFAULT NULL COMMENT '创建时间', `modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)', `modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间', `providerId` INT(20) DEFAULT NULL COMMENT '供应商ID', PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE `smbms_provider` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `proCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商编码', `proName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商名称', `proDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商详细描述', `proContact` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商联系人', `proPhone` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系电话', `proAddress` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址', `proFax` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '传真', `createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)', `creationDate` DATETIME DEFAULT NULL COMMENT '创建时间', `modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间', `modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)', PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE `smbms_role` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `roleCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色编码', `roleName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名称', `createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者', `creationDate` DATETIME DEFAULT NULL COMMENT '创建时间', `modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者', `modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- auto-generated definition create table smbms_user ( id bigint auto_increment comment '主键ID' primary key, userCode varchar(15) null comment '用户编码', userName varchar(15) null comment '用户名称', userPassword varchar(15) null comment '用户密码', gender int(10) null comment '性别(1:女、 2:男)', birthday date null comment '出生日期', phone varchar(15) null comment '手机', address varchar(30) null comment '地址', userRole int(10) null comment '用户角色(取自角色表-角色id)', createdBy bigint null comment '创建者(userId)', creationDate datetime null comment '创建时间', modifyBy bigint null comment '更新者(userId)', modifyDate datetime null comment '更新时间' ) collate = utf8_unicode_ci;
public class BaseEntity { private Integer createdBy; //创建者 private Date creationDate; //创建时间 private Integer modifyBy; //更新者 private Date modifyDate; //更新时间 public BaseEntity(){ createdBy = 1; creationDate = new Date(); } }
package com.hopeful.pojo; import lombok.Data; import java.math.BigDecimal; /** * Bill * * @author : yl * @version : [v1.0] * @createTime : [2021/9/3 7:26] */ @Data public class Bill extends BaseEntity { private Integer id; // id private String billCode; // 账单编码 private String productName; //商品名称 private String productDesc; //商品描述 private String productUnit; //商品单位 private BigDecimal productCount; //商品数量 private BigDecimal totalPrice; //总金额 private Integer isPayment; //是否支持 private Integer providerId; //供养商ID private String providerName; //供应商名称 }
package com.hopeful.pojo; /** * Provider * * @author : yl * @version : [v1.0] * @createTime : [2021/9/3 7:39] */ public class Provider extends BaseEntity { private Integer id; // id private String proCode; //供养商编码 private String proDesc; //供养商描述 private String proContact; //供养商联系人 private String proPhone; //供养商电话 private String proAddress; // 供养商地址 private String proFax; //供应商传真 private String companyLicPicPath; //企业营业执照的存储路径 private String orgCodePicPath; //组织机构的代码证的存储路径 }
package com.hopeful.pojo; /** * Role * * @author : yl * @version : [v1.0] * @createTime : [2021/9/3 7:55] */ public class Role extends BaseEntity { private Integer id; // id private String roleCode; //角色编码 private String roleName; //角色名称 }
package com.hopeful.pojo; import java.util.Date; /** * User * * @author : yl * @version : [v1.0] * @createTime : [2021/9/3 7:58] */ public class User extends BaseEntity{ private Integer id; // id private String userCode; // 用户编码 private String userName; //用户名称 private String userPassword; //用户密码 private Integer gender; //性别 private Date birthday; private String phone; //电话 private String address; //地址 private Integer userRole; //用户角色 private Integer createdBy; //创建者 private Date creationDate; //创建时间 private Integer modifyBy; //更新者 private Date modifyDate; //更新时间 private Integer age;//年龄 private String userRoleName; //用户角色名称 }
Spring下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring