二,MyBatis -Plus 关于映射 Java Bean 对象的注意事项和细节(详细说明)
文章目录
- 二,MyBatis -Plus 关于映射 Java Bean 对象的注意事项和细节(详细说明)
- 1. 映射
- 2. 表的映射
- 3. 字段映射
- 4. 字段失效
- 5. 视图属性
- 6. 总结:
- 7. 最后:
1. 映射
这里的映射:是指将从数据库查询到的信息,映射到对应的Java Bean对象当中的。
学习过Mybatis的同学应该知道,Mybatis框架之所以能够简化数据库操作,是因为他内部的映射机制,通过自动映射,进行数据的封装,我们只要符合映射规则,就可以快速高效的完成SQL操作的实现。
既然MybatisPlus是基于Mybatis的增强工具,所以也具有这样的映射规则。
我们先来了解一下自动映射规则。
- 表名和实体类名映射 -> 表名user 实体类名User
- 字段名和实体类属性名映射 -> 字段名name 实体类属性名name
- 字段名下划线命名方式和实体类属性小驼峰命名方式映射 ->
- 简单的说就是:**MyBatis-plus 将数据表当中的查询到的信息赋值到 对应Java bean 对象当中是,通过 反射机制当中,使用 setName->Name->name进行赋值操作的。并不是通过,bean 对象当中的属性名执行赋值的 **
字段名 user_email 实体类属性名 userEmail
MybatisPlus支持这种映射规则,可以通过配置来设置
map-underscore-to-camel-case: true 表示支持下划线到驼峰的映射 map-underscore-to-camel-case: false 表示不支持下划线到驼峰的映射
这里我们在
applicaition.yaml
文件当中进行配置。
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false username: root password: MySQL123 main: banner-mode: off #关闭 spring boot 在命令行当中的图标显示 mybatis-plus: global-config: banner: false # 关闭 mybatis-plus 在命令行当中的图标显示 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启 Log 日志信息打印 map-underscore-to-camel-case: true # 开启驼峰,下划线映射规则
2. 表的映射
通过 @TableName()
注解指定映射的数据库表名,就会按照指定的表名进行映射。
表映射:主要用于,当我们的数据表名与 我们在Java当中创建的实体类的 Java Bean 不一致的时候。那么 MyBatis Plus 是无法为我们进行 实体类上的映射的,会报错。这时候,我们就需要通过
@TableName()
注解的当中的 value 属性对其进行操作,让我们的Java Bean 实体类 与 数据表名保持一致 。
这时我们添加上@TableName()
注解,指明该实体类,映射的数据表是哪一个。
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
如果有很多实体类,对应到数据库中的很多表,我们不需要每个依次配置,只需要配置一个全局的设置,他都会给每个实体类名前面添加指定的前缀,这里我们演示一下全局配置的效果.
当多个实体类,存在有规律,有统一前缀的时候,我们可以在
application.yaml
文档当中,配置,所有实体类映射的前缀。当 MyBatis Plus 执行 SQL 语句的时候,会将我们配置的 前缀拼接上,然后,在进行一个执行 SQL语句。如下:**注意:该配置是全局性的,作用于整个 MyBatis -plus **
mybatis-plus: global-config: banner: false # 关闭 mybatis-plus 在命令行当中的图标显示 db-config: table-prefix: rainbowsea_ # 还可以通过统一添加前缀的方式:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false username: root password: MySQL123 main: banner-mode: off #关闭 spring boot 在命令行当中的图标显示 mybatis-plus: global-config: banner: false # 关闭 mybatis-plus 在命令行当中的图标显示 db-config: table-prefix: rainbowsea_ # 还可以通过统一添加前缀的方式: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启 Log 日志信息打印 map-underscore-to-camel-case: true # 开启驼峰,下划线映射规则
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
3. 字段映射
什么场景下会改变字段映射呢?
当数据库字段和表实体类的属性不一致时,我们可以使用@TableField()
注解改变字段和属性的映射,让注解中的名称和表字段保持一致。
当我们数据表当中的字段名与我们Java Bean 实体类当中的属性名不一致的时候,运行程序,想要将查询结果赋值到对应的实体类上时,是会报错的。这时候,我们就可以在实体类的属性名上加上
@TableField()
注解,并将其value 值指定为数据表中对应的字段名
。这样当执行 SQL 语句的时候,MyBatis Plus 会通过该注解标注指定的字段属性进行一个as
别名的方式,让其赋值到对应Java Bean 实体类的属性上。
如:此时将数据库字段的名称我们改为username,在根据实体类的属性拼接SQL的使用,就会使用@TableField()中指定的名称username进行拼接,完成查询
在实体类当中的与数据表不一致的属性名上,我们使用上 @TableField()
注解的方式,进行指明为数据表当中的哪个字段名。
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
private Long id;
@TableField(value = "username")
private String name;
private Integer age;
private String email;
}
当我们执行的 SQL语句当中包含了 SQL语句的关键字 ,如果没有使用别名特殊,处理的话,是会报错的。如下:
数据库字段和表实体类的属性一致,框架在拼接SQL语句的时候,会使用属性名称直接拼接sql语句,例如:
SELECT id,username AS name,age,email,desc FROM `rainbowsea_user`
这条语句直接进行查询的时候,会出现错误
Error querying database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘desc FROM rainbowsea_user’ at line 1。
原因是,desc属于关键字,不能直接用于sql查询,要解决这个问题,就需要将desc字段加上 “`” 符号,将他变为不是关键字,才能完成查询,那这个问题的根本也是改变生成的SQL语句的字段名称,也就是我们需要通过@TableField()改变实体类的属性名称,将desc变为desc,就可以解决这个问题。运行测试。
如果我们Java Bean 实体类当中,有这样一个
desc
SQL语句的关键字,作为了该实体类当中的属性名,那么执行 SQL语句的时候,涉及到查询该属性名时,就会报错。
我们需要通过@TableField()
改变实体类的属性名称,将 desc 变为 desc , 就可以解决这个问题。运行测试。
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
private Long id;
@TableField(value = "username")
private String name;
@TableField(select = false) // 查询时,不对age 字段进行查询
private Integer age;
private String email;
@TableField(value = "`desc`") // 注意:有两层,但最里面的哪个不是引号
private String desc;
}
再次运行测试:
此时可以观察到,框架拼接生成的SQL语句的字段名称变为了desc
,这样是可以正常完成查询的
4. 字段失效
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
@TableField(select = false) // 查询时,不对age 字段进行查询
private Integer age;
}
当数据库中有字段不希望被查询,我们可以通过 @TableField(select = false)
来隐藏这个字段,那在拼接SQL语句的时候,就不会拼接这个字段。
如:如果不想显示年龄信息,那么可以在age属性上添加这个注解,来隐藏这个字段。
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
private Long id;
@TableField(value = "username")
private String name;
@TableField(select = false) // 查询时,不对age 字段进行查询
private Integer age;
private String email;
}
5. 视图属性
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
@TableField(exist = false) // 表示,不让该 online 属性,作为 SQL语句当中的查询字段
private Integer online;
}
在实际开发中,有些字段不需要数据库存储,但是却需要展示,需要展示也就是意味着实体类中需要存在这个字段,我们称这些实体类中存在但是数据库中不存在的字段,叫做视图字段。
根据之前的经验,框架会默认将实体类中的属性作为查询字段进行拼接,那我们来思考,像这种视图字段,能够作为查询条件么,显示是不能的。因为数据库中没有这个字段,所以查询字段如果包含这个字段,SQL语句会出现问题。我们通过@TableField(exist = false)
来去掉这个字段,不让他作为查询字段。
package com.rainbowsea.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName(value = "rainbowsea_user") // 指明该实体类映射的是那张数据表
//@TableName(value = "user")
public class User {
private Long id;
@TableField(value = "username")
private String name;
@TableField(select = false) // 查询时,不对age 字段进行查询
private Integer age;
private String email;
@TableField(value = "`desc`") // 注意:有两层,但最里面的哪个不是引号
private String desc;
@TableField(exist = false) // 表示,不让该 online 属性,作为 SQL语句当中的查询字段
private Integer online;
}
6. 总结:
- 映射:是指将从数据库查询到的信息,映射到对应的Java Bean对象当中的。
@TableName()
注解的当中的 value 属性对其进行操作,让我们的Java Bean 实体类 与 数据表名保持一致 。@TableField()
注解改变字段和属性的映射,让注解中的名称和表字段保持一致。同时也可以运用于,当属性名与SQL关键字冲突的时候,可以使用@TableField(value = "
desc")
,注意:含有关键字的时候,有两层包含的,最后一个不是单引号 。@TableField(select = false)
来隐藏这个字段,那在拼接SQL语句的时候,就不会拼接这个字段。@TableField(select = false)
来隐藏这个字段,那在拼接SQL语句的时候,就不会拼接这个字段。@TableField(exist = false)
来去掉这个字段,不让他作为查询字段。
7. 最后:
“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”