??通用 Mapper 默认使用了几个简单的注解,其他 JPA 的注解默认并不支持,但是如果你开发自己的通用方法,你可以使用 JPA 注解或者引入自己的注解。
@NameStyle 注解(Mapper) 名字转换样式,注解的优先级高于全局配置,主要有以下几个值:
normal, //原值
camelhump, //驼峰转下划线
uppercase, //转换为大写
lowercase, //转换为小写
camelhumpAndUppercase, //驼峰转下划线大写形式
camelhumpAndLowercase, //驼峰转下划线小写形式
示例:
@NameStyle(value = Style.camelhump)
public class Role {
}
@Table 注解(JPA) 此注解指定注解实体的主表,将实体类和数据库表进行关联映射。@Table 注解可以配置 name,catalog 和 schema 三个属性,配置 name 属性后,直接使用提供的表名,不再根据实体类名进行转换。其他两个属性中,同时配置时,catalog 优先级高于 schema,也就是只有 catalog 会生效。 示例:
@Table(name = "`role`")
public class Role {
}
@Column 注解(JPA) 将实体类属性和数据库表字段进行关联映射。@Column 注解支持 name, insertable 和 updateable 三个属性。name 配置映射的列名;insertable 对提供的 insert 方法有效,如果设置 false 就不会出现在 SQL 中;updateable 对提供的 update 方法有效,设置为 false 后不会出现在 SQL 中。 示例:
public class Role {
@Column(name = "`role_name`",insertable = true,updatable = false)
private String roleName;
}
@ColumnType 注解(Mapper) 针对列的复杂属性配置,这个注解提供的 column属性和 @Column 中的 name 作用相同。但是 @Column 的优先级更高。除了 name 属性外,这个注解主要提供了 jdbcType 属性和 typeHandler 属性。jdbcType 用于设置特殊数据库类型时指定数据库中的 jdbcType。typeHandler 用于设置特殊类型处理器,常见的是枚举。 示例:
public class Role {
@ColumnType(column = "`role_name`",jdbcType = JdbcType.VARCHAR,typeHandler = StringTypeHandler.class)
private String roleName;
}
@Transient 注解(JPA) 一般情况下,实体中的字段和数据库表中的字段是一一对应的,但是也有很多情况我们会在实体中增加一些额外的属性,这种情况下,就需要使用 @Transient 注解来告诉通用 Mapper 这不是表中的字段。 示例:
public class Role {
@Transient
private String uid;
}
@Id 注解(JPA) @Id 注解和映射无关,它是一个特殊的标记,用于标识数据库中的主键字段。正常情况下,一个实体类中至少需要一个标记 @Id 注解的字段,存在联合主键时可以标记多个。如果表中没有主键,类中就可以不标记。
public class Role {
@Id
@Column(name = "`id`")
private String id;
}
@KeySql @GeneratedValue 注解 这两个注解都是主键策略注解,用于配置如何生成主键。
??除了主键策略注解,其他注解在实际开发中会多或少都会使用,接下来就详细说说主键策略注解的使用。
??首先主键策略和数据库关系很大,有些数据库支持主键自增,而有些数据库只能通过序列来获得。通用mapper新增的@KeySql 注解用于替换 @GeneratedValue 注解,因此 @KeySql 能以更简单方式实现原来的功能。
??首先看看 @KeySql 注解 ,通过源码可以看出,@KeySql 不仅支持通过JDBC的方式获取自增主键,例如用于MySQL;同时也可以通过自定义SQL的方式获取主键值,例如用于Oracle;并且也可以自定义生成主键值的方法,例如用于全局主键,在使用时请注意优先级。
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface KeySql {
boolean useGeneratedKeys() default false;
IdentityDialect dialect() default IdentityDialect.NULL;
String sql() default "";
Class<? extends GenSql> genSql() default GenSql.NULL.class;
ORDER order() default ORDER.DEFAULT;
Class<? extends GenId> genId() default GenId.NULL.class;
}
??而 @GeneratedValue 就只有两个属性,在使用时需要同时使用xml映射方法实现
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {
GenerationType strategy() default AUTO;
String generator() default "";
}
1. 自增主键的数据库主键策略 ??常见的支持自增主键的数据库如下,自增主键的值主要通过数据库自己管理,所以存值时是不需要我们过多的去干涉;而自增主键取回主键值主要是通过数据库提供的 JDBC 支持 getGeneratedKeys 方法
DB2: VALUES IDENTITY_VAL_LOCAL()
MYSQL: SELECT LAST_INSERT_ID()
SQLSERVER: SELECT SCOPE_IDENTITY()
CLOUDSCAPE: VALUES IDENTITY_VAL_LOCAL()
DERBY: VALUES IDENTITY_VAL_LOCAL()
HSQLDB: CALL IDENTITY()
SYBASE: SELECT @@IDENTITY
DB2_MF: SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
INFORMIX: select dbinfo('sqlca.sqlerrd1') from systables where tabid=1
@KeySql 示例:
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
@Id
@KeySql(dialect = IdentityDialect.DEFAULT)
private Integer id;
@Id
@KeySql(dialect = IdentityDialect.MYSQL)
private Integer id;
注意:SqlServer 中使用时,需要设置 id 的 insertable=false ??同时也可以通过 dialect 参数,根据配置的数据库类型取回主键,它的优先级比 useGeneratedKeys 低,参数值有以下集中
DB2("VALUES IDENTITY_VAL_LOCAL()"),
MYSQL("SELECT LAST_INSERT_ID()"),
SQLSERVER("SELECT SCOPE_IDENTITY()"),
CLOUDSCAPE("VALUES IDENTITY_VAL_LOCAL()"),
DERBY("VALUES IDENTITY_VAL_LOCAL()"),
HSQLDB("CALL IDENTITY()"),
SYBASE("SELECT @@IDENTITY"),
DB2_MF("SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"),
INFORMIX("select dbinfo('sqlca.sqlerrd1') from systables where tabid=1"),
DEFAULT(""),
NULL("");
@GeneratedValue示例:
@Id
@Column(name = "`id`")
@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "JDBC")
private String id;
<insert id="insert">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into country (id, countryname, countrycode)
values (#{id},#{countryname},#{countrycode})
</insert>
2. 序列和任意 SQL 的数据库主键策略 ??像 Oracle 中通过序列获取主键就属于这种情况,实际上 2.3.2 中的 SQL 也可以在这里配置。除了类似序列获取值外,还可以是获取 UUID 的 SQL 语句,例如 select uuid()。 @KeySql示例:
@Id
@KeySql(sql = "select SEQ_ID.nextval from dual", order = ORDER.BEFORE)
private Integer id;
@GeneratedValue示例:
@Id
@Column(name = "`id`")
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select uuid()")
private String id;
<insert id="insert">
<selectKey keyProperty="id" resultType="String" order="BEFORE">
select uuid()
</selectKey>
insert into dept (id, dept_name)
values (#{id},#{deptName})
</insert>
3. 全局主键 ??通用 Mapper 4.0.2+ 版本增加了新的控制主键生成的策略 genId() 属性,可以自己定义主键生成策略。使用该功能需要自己去实现生成的方法,可以用于全局主键。 示例:
public class TimeStampSql implements GenId {
private Long time;
private Integer seq;
@Override
public synchronized Object genId(String table, String column) {
long current = System.currentTimeMillis();
if (time == null || time != current) {
time = current;
seq = 1;
} else if (current == time) {
seq++;
}
return ((time << 20) | seq) + "";
}
}
public class UUIDSql implements GenId {
@Override
public Object genId(String table, String column) {
return UUID.randomUUID().toString().replace("-", "");
}
}
@Id
@Column(name = "`id`")
@KeySql(genId = UUIDSql.class)
private String id;
源码地址:https://gitee.com/peachtec/hxz-study
|