本章目录
1.4.2 mapUnderscoreToCamelCase属性
?数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。
?狭义的讲就是将内存中的数据存储到数据库或其他介质的过程。
Dao层将数据存储到数据库中
?Java如何实现数据持久化?
JDBC编程操作:
Mybatis、Hibernate等框架技术
MyBatis的前身是iBatis,是在2001年发起的一个开源项目,2010年更名为MyBatis,是目前企业级数据库操作使用最多的框架之一。
MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架,几乎封装所有的JDBC代码和参数的手动设置以及结果集的检索,通过XML或注解的方式进行配置映射实现数据库操作,大大提高了开发效率。
?MyBatis优势:
在Eclipse中创建一个基本的Maven项目,操作步骤如下:
查找地址:https://mvnrepository.com/
?
?要使用Mybatis实现数据库操作,首先需要在 src/main/resources 目录下创建mybatis核心配置文件mybatis-config.xml。
?别名配置: ?
<typeAliases>
<package name="jack.mybatis.simple.model" />
</typeAliases>
项目中实体类包名,配置后mybatis才识别实体类名称
操作具体表的SQL语句映射文件:
<mappers>
<mapper resource="jack/mybatis/mapper/CountryMapper.xml"/>
</mappers>
映射文件完整路径
?具体数据源配置(可以配置多个,选择其中一个使用):
<environments default=“development”> <!-定义数据源,默认使用第一个-->
<environment id="development"> <!-- 每个environment元素定义的环境id-->
<dataSource type="UNPOOLED"> <!-- 数据源配置 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db_mybatis" />
<property name="username" value="root" />
<property name="password" value="abc123" />
</dataSource>
</environment>
</environments>
?MyBatis是一个结果映射框架,创建一个和数据库表对应的实体类。
在实体类包(jack.mybatis.simple.model)下新建实体类 Country
public class Country {
private String countrycode;
private String countryname;
private Long id;
// 属性getter()方法和setter()方法
}
?在src/main/resources下面创建 jack/mybatis/simple/mapper 目录,该目录下面创建与实体类Country对应的映射文件CountryMapper.xml文件
<!-- 映射器名字空间,即CountryMapper类的全限定名称 -->
<mapper namespace="jack.mybatis.simple.mapper.CountryMapper">
<select id="selectAll" resultType="Country">
select id,countryname,countrycode from country
</select>
</mapper>
id="selectAll"? ? ? ? ? id和接口方法名对应
resultType="Country"? ? ? ?resultType代表返回的结果类型,和实体类对应
namespace="jack.mybatis.simple.mapper.CountryMapper"? ? ? ? ??mybatis会自动产生该接口
CountryMapper名称必须是实体类+Mapper组合 <select>标签对应查询语句,还有insert、update、delete标签对应
?Log4j用于将MyBatis执行过程中的SQL和其他信息输出到控制台:
在src/main/resources中添加log4j.properties配置文件,代码如下:
#全局配置
log4j.rootLogger=ERROR, stdout
#MyBatis日志配直
log4j.logger.jack.mybatis.simple.mapper=TRACE
#控制台输出配置
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
?在src/test/java中创建jack.mybatis.simple.mapper包,然后创建CountryMapperTest测试类,以下为测试类初始化方法:
1、完成mybatis配置的加载,创建得到SqlSessionFactory
@BeforeClass
public static void init () {
try {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); 加载配置文件,创建SqlSessionFactory
2、从SqlSessionFactory对象中获取SqlSession对象,用于调用方法得到数据:
@Test
public void testSelectAll() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
List<Country> countryList = sqlSession.selectList("selectAll");
//调用打印数据方法,也可以这里输出
printCountryList(countryList);
} finally {
// 不要忘记关闭sqlSession
sqlSession.close();
}
}
SqlSession sqlSession = sqlSessionFactory.openSession();? ? ?得到SqlSession对象
List<Country> countryList = sqlSession.selectList("selectAll");? ? ? 调用方法查询数据 selectAll为xml映射文件中定义的查询id
?
权限控制系统中,一个用户拥有若干角色,一个角色拥有若干权限。权限就是对某个资源(模块)的某种操作(增、删、改、查),这样就构成了“用户—角色—权限”的授权模型。
?使用MyBatis实现根据用户id获取用户信息的步骤如下:
创建maven项目,添加mybatis依赖支持
创建实体类包和用户实体类SysUser.java
package entity;
public class SysRole {
private long id;
private String roleName;
private int enabled;
private String createBy;
private String createTime;
public SysRole() {
super();
}
public SysRole(long id, String roleName, int enabled, String createBy, String createTime) {
super();
this.id = id;
this.roleName = roleName;
this.enabled = enabled;
this.createBy = createBy;
this.createTime = createTime;
}
@Override
public String toString() {
return "SysRole [id=" + id + ", roleName=" + roleName + ", enabled=" + enabled + ", createBy=" + createBy
+ ", createTime=" + createTime + "]";
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public int getEnabled() {
return enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}
一般表中int在实际中会使用Integer和Long
byte[]一般对应blob等二进制流类型
?创建对实体进行DAO操作的映射器接口
public interface UserMapper {
// 根据用户id查询一个用户实体
public SysUser selectById(Long id);
}
id是查询的参数条件值
这里自己定义了操作的接口,接口中方法无需实现,由mybatis运行时进行实现
?在resources对应目录下定义接口的映射配置文件:UserMapper.xml
<mapper namespace="jack.mybatis.authority.mapper.UserMapper">
<resultMap type="SysUser" id="userMap">
详细映射说明
</resultMap>
<select id="selectById" resultMap="userMap">
select * from sys_user where id = #{id}
</select>
</mapper>
如果实体类中属性名和表列名一致,resultMap="userMap">可以直接写resultType
id为接口定义传入的参数名
<resultMap type="SysUser" id="userMap">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<result property="userEmail" column="user_email"/>
<result property="userInfo" column="user_info"/>
<result property="headImg" column="head_img" jdbcType="blob"/>
<result property="createTime" column="create_time" jdbcType="timestamp"/>
</resultMap>
实体类中的属性名和数据表的列名不对应,运行会直接报错,需要添加映射说明
?配置mybatis-config.xml核心配置文件
<environment id="development"> <!-- 每个environment元素定义的环境id-->
<dataSource type="UNPOOLED"> <!-- 数据源配置 -->
<property name=“driver” value=“com.mysql.jdbc.Driver” />
<property name=“url” value=“jdbc:mysql://localhost:3306/数据库名" />
<property name="username" value="root" />
<property name="password" value="abc123" />
</dataSource>
</environment>
<!--加入对接口映射文件的注册识别,否则mybatis无法正常运行-->
<mappers>
<mapper resource="jack/mybatis/authority/mapper/UserMapper.xml" />
</mappers>
一定要将接口映射xml文件注册到mybatis核心配置中
?测试实现,关键代码如下:
//加载mybatis配置文件代码略
//获取SqlSessionFactory对象
//获取接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用selectByid方法,查询id=1的用户
SysUser user = userMapper.selectById(1L);
printUser(user);
自己定义接口的方式需要获取接口代理对象
?
resultType用于定义返回或者参数的类型,如果返回的是集合则只需要定义集合中的实体类型即可,如果未在核心配置中指明typeAliases,则需要写全路径名。
public List<SysUser> selectUsers(); ?
resultMap用于定义当查询的结果字段和接收的实体类字段不一致时,进行映射说明,如下:
<resultMap type="SysUser" id="userMap">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<result property="userEmail" column="user_email"/>
</resultMap>
property="userName" 对应实体中属性名
column="user_name" 对应表中的列名
数据库中下划线方式的命名很常见,但是Java中而是使用驼峰式命名,如userName、userEmail等,这样mybatis在结果返回和实体类对应时无法直接关联,需要定义resultMap增加了复杂度。
MyBatis提供了一个全局属性mapUnderscoreToCamelCase,通过配置该属性为true可以自动将以下划线方式命名的数据库列映射到Java对象的驼峰式命名属性中。
<settings>
<!—其他配置-->
<!--将以下划线方式命名的数据库列映射到Java对象的驼峰式命名属性中-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
实际业务中还需要多表关联查询。关联查询结果的类型也会有多种情况:
情况1:多表查询结果只包含一个表的信息 根据用户id获取用户拥有的所有角色,虽然查询时关联三个表,但是返回的结果为角色集合,查询结果只有角色的信息。
// 根据用户id获取角色信息
List<SysRole> selectRolesByUserid(Long id);
<!—对应映射xml中的sql和配置-->
<select id="selectRolesByUserid" resultType="SysRole">
select r.id,r.role_name roleName,r.enabled,r.create_by createBy,r.create_time createTime
from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u on u.id=ur.user_id
where u.id=#{userId}
</select>
情况2:多表查询结果包含多个表的信息
根据用户id获取用户拥有的所有角色,假设查询的结果不仅要包含角色信息,还要包含当前用户的部分信息(不考虑嵌套的情况)
解决1:在SysRole对象中直接添加userName属性,这样仍然使用SysRole作为返回值
解决2:创建一个新类SysRoleExtend继承SysRole,如下:
public class SysRoleExtend extends SysRole{
private String userName; //添加SysRole中没有的属性,而查询结果中需要包含的
…. 其他需要包含的
//产生get和set方法
}
?将resultType设置为扩展属性后的SysRoleExtend对象,通过这种方式来接收多余的值,如果需要其他表中大量列的值时,这种方式就不适用了,因为我们不能将一个类的属性都照搬到另一个类中。
?情况3: 使用对象作为成员属性的方式接收多表数据,需要角色SysRole的数据,还需要SysUser的数据,而SysRole中无法存储SysUser的数据,所以直接将一个SysUser对象放入SysRole中作为成员属性。
public class SysRole {
// 其他原有属性
private SysUser user; // 用户信息
...
}
该属性是一个用户对象, 可以将查询的用户信息封装进去
?修改UserMapper.xml中selectRolesByUserid的SQL,达到能够将用户的数据放入SysUser成员属性对象中,代码如下:
<select id="selectRolesByUserid" resultType="SysRole">
select r.id,r.role_name,r.enabled,r.create_by,r.create_time,u.user_name as "user.userName" from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u on u.id=ur.user_id where u.id=#{userId}
</select>
红色的为列的别名,user则对应SysRole实体中的user实体对象名
?
?
互联网业务往往使用MySQL数据库作为后台存储,存储引擎使用InnoDB。我们针对互联...
使用REPLACE来将数据库里读出来的数据替换,如果字段不为空是正常,但如果 为空时...
一、金融行业架构转型需求 随着移动化与互联网化的不断发展,我国金融行业的商业...
先扫盲一下什么是正则表达式的贪婪,什么是非贪婪?或者说什么是匹配优先量词,...
重新编译jsp是不用重启服务期的,但类就需要。 所以需要设置一下:: 在weblogic...
谷歌的Tilt Brush并不免费,但随着这款VR艺术创作工具的开源,社区开始陆续捣鼓...
系列文章目录 文章目录 系列文章目录 前言 一、旋转数组 1.题目描述 2.解题思路 ...
【Java知识点】面试中会问到的那些小知识2为什么接口中没有构造方法而抽象类中有...
本文实例讲述了php多进程中的阻塞与非阻塞操作。分享给大家供大家参考,具体如下...
.Net Core中有各种Filter,分别是AuthorizationFilter、ResourceFilter、Exceptio...