持久层、@Table、@JoinTable、多数据源、MyBatis

引言

持久层实体类采用 @Table注解配置,自动生成增删改通用SQL,不需要在mapper.xml里写重复又费时的SQL,遇见复杂的情况下支持扩展。而报表统计分析的情况下又能支持mybatis原生写法,在写sql的时候,又能调用之前实体配置的一些参数。从而减少开发和后期维护成本。

众多的持久层框架@Column注解定义都是分布到get或属性上,或者干脆直接使用属性作为字段名,这在JeeSite是不推荐的,JeeSite的实体不仅仅是物理实体,它是与Model实体结合的一个产物。综合考虑,将@Column所有定义到类头,而不是分布到各个属性或方法上,主要是有以下三点原因:

  • 可一览熟知该实体类对应的物理表结构是什么样,引领开发者思维从物理表结构到对象的映射转换,都是基于物理表结构的,@Column中的name指定物理字段名,而不是指定类上的属性名,也是这个原因;
  • 自动化生成的SQL和查询条件,是有序的,可方便核查定义,有利于优化查询性能;
  • 方便@JoinTable关联表和其它扩展信息的设置,如果分布到类的属性上就需要来回滚动屏幕查找,不利于管理字段列。

简单举例

以定义员工实体举例,配置如下:(注意代码上的注释)

  1. @Table(name="${_prefix}sys_employee", alias="a", columns={
  2. // 支持Include,如:自动导入status、create_by、create_date等字段
  3. @Column(includeEntity=BaseEntity.class),
  4. @Column(includeEntity=DataEntity.class),
  5. // 支持设置主键PK字段,调用get方法时自动加入主键唯一条件
  6. @Column(name="emp_code", label="员工编码", isPK=true),
  7. // 支持设置查询字段类型,如LIKE自动在查询值前后加 % 符号。
  8. @Column(name="emp_name", label="名称", queryType=QueryType.LIKE),
  9. @Column(name="emp_name_en", label="英文名", queryType=QueryType.LIKE),
  10. // 字段名到Java属性名的转换,采用驼峰命名法规则自动进行转换
  11. @Column(name="emp_no", label="工号"),
  12. // 驼峰命名法转换不了的,支持设置特殊对象属性,如mapper.xml的sql中 a.office_code AS "office.officeCode" 的写法
  13. @Column(name="office_code", attrName="office.officeCode", label="机构编码"),
  14. @Column(name="office_name", attrName="office.officeName", label="机构名称", queryType=QueryType.LIKE),
  15. @Column(name="company_code", attrName="company.companyCode", label="公司编码"),
  16. @Column(name="company_name", attrName="company.companyName", label="公司名称", queryType=QueryType.LIKE),
  17. @Column(name="sex", label="性别"),
  18. @Column(name="birthday", label="生日"),
  19. // 支持设置非查询字段,添加查询条件时忽略该字段
  20. @Column(name="photo", label="员工照片", isQuery=false),
  21. @Column(name="email", label="电子邮件"),
  22. @Column(name="mobile", label="手机号码"),
  23. @Column(name="phone", label="办公电话"),
  24. @Column(name="fax", label="传真号码"),
  25. @Column(name="qq", label="QQ号"),
  26. @Column(name="weixin", label="微信号"),
  27. @Column(name="stations", label="岗位"),
  28. },
  29. // 支持联合查询,如左右连接查询,支持设置查询自定义关联表的返回字段列
  30. joinTable={
  31. @JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
  32. on="o.office_code = a.office_name",
  33. columns={@Column(includeEntity=Office.class)}),
  34. @JoinTable(type=Type.LEFT_JOIN, entity=Company.class, alias="c",
  35. on="c.company_code = a.company_name",
  36. columns={@Column(includeEntity=Company.class)}),
  37. },
  38. // 支持扩展Column、Form、Where等,主要用于该注解实现不了的复杂情况,扩展SQL写法,这里设置的是sqlMap的key
  39. extWhereKeys="dsfOffice, dsfCompany",
  40. // 自动设置默认排序
  41. orderBy="a.update_date DESC"
  42. )
  43. public class Employee extends DataEntity<Employee> {
  44. private static final long serialVersionUID = 1L;
  45. private String empCode; // 员工编码
  46. private String empName; // 名称
  47. private String empNameEn; // 英文名
  48. private String empNo; // 工号
  49. private Office office; // 机构编码
  50. private Company company; // 公司编码
  51. private String sex; // 性别
  52. private Date birthday; // 生日
  53. private String photo; // 员工照片
  54. private String email; // 电子邮件
  55. private String mobile; // 手机号码
  56. private String phone; // 办公电话
  57. private String fax; // 传真号码
  58. private String qq; // QQ号
  59. private String weixin; // 微信号
  60. private String stations; // 岗位
  61. /// 省略 get set 方法
  62. }

请仔细看上面的代码和注释,其以上之外,还支持是否为插入字段,是否为更新字段等等。

再举一个例子,扩展上面介绍的Employee表,与用户表联合查询单独定义实体,用户员工实体:

  1. @Table(name="${_prefix}sys_user", alias="a", columns={
  2. @Column(includeEntity=User.class),
  3. }, joinTable={
  4. @JoinTable(type=Type.JOIN, entity=Employee.class, alias="e",
  5. on="e.emp_code = a.ref_code AND a.user_type=#{USER_TYPE_EMPLOYEE}",
  6. columns={@Column(includeEntity=Employee.class)}),
  7. @JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
  8. on="o.office_code = a.office_name", attrName="employee.office",
  9. columns={@Column(includeEntity=Office.class)}),
  10. @JoinTable(type=Type.LEFT_JOIN, entity=Company.class, alias="c",
  11. on="c.company_code = a.company_name", attrName="employee.company",
  12. columns={@Column(includeEntity=Company.class)}),
  13. }, extWhereKeys="dsfOffice, dsfCompany", orderBy="a.update_date DESC"
  14. )
  15. public class EmpUser extends User {
  16. private static final long serialVersionUID = 1L;
  17. public EmpUser() {
  18. this(null);
  19. }
  20. public EmpUser(String id){
  21. super(id);
  22. }
  23. @Valid
  24. public Employee getEmployee(){
  25. Employee employee = (Employee)super.getRefObj();
  26. if (employee == null){
  27. employee = new Employee();
  28. }
  29. return employee;
  30. }
  31. public void setEmployee(Employee employee){
  32. super.setRefObj(employee);
  33. }
  34. }

注解配置完成了,下面看看如何使用

如何使用

贴了这么多配置代码,下面介绍下用法。

你的Dao只需要继承CrudDao即可享受便捷体验,是不是特Easy,如下:

  1. /**
  2. * 员工管理DAO接口
  3. * @author ThinkGem
  4. */
  5. @MyBatisDao(entity = Employee.class)
  6. public interface EmployeeDao extends CrudDao<Employee> {
  7. }

EmployeeDao继承CrudDao后,里面的方法你都可以调用,如下方法:

  1. /**
  2. * DAO实现增删改接口
  3. * @author ThinkGem
  4. */
  5. public interface CrudDao<T> extends QueryDao<T> {
  6. /**
  7. * 插入数据
  8. */
  9. public int insert(T entity);
  10. /**
  11. * 批量插入数据
  12. */
  13. public int insertBatch(List<T> entityList);
  14. /**
  15. * 更新数据 By PK
  16. */
  17. public int update(T entity);
  18. /**
  19. * 更新数据 By Entity
  20. * 调用此方法前,请务必检查whereEntity的数据准确性,否则可能会造成不想要更新的数据被更新
  21. */
  22. public int updateByEntity(T entity, T whereEntity);
  23. /**
  24. * 更新状态数据 By PK
  25. */
  26. public int updateStatus(T entity);
  27. /**
  28. * 更新状态数据 By Entity
  29. * 调用此方法前,请务必检查whereEntity的数据准确性,否则可能会造成不想要更新的数据被更新
  30. */
  31. public int updateStatusByEntity(T entity, T whereEntity);
  32. /**
  33. * 删除数据 By PK(如果有status字段,则为逻辑删除,更新status字段为1,否则物理删除)
  34. */
  35. public int delete(T whereEntity);
  36. /**
  37. * 删除数据 By Entity(如果有status字段,则为逻辑删除,更新status字段为1,否则物理删除)
  38. * 调用此方法前,请务必检查whereEntity的数据准确性,否则可能会造成不想要更新的数据被更新
  39. */
  40. public int deleteByEntity(T whereEntity);
  41. /**
  42. * 物理数据 By PK
  43. */
  44. public int phyDelete(T whereEntity);
  45. /**
  46. * 物理数据 By Entity
  47. * 调用此方法前,请务必检查whereEntity的数据准确性,否则可能会造成不想要更新的数据被更新
  48. */
  49. public int phyDeleteByEntity(T whereEntity);
  50. /**
  51. * 获取单条数据
  52. * @param entity
  53. * @return entity
  54. */
  55. public T get(T entity);
  56. /**
  57. * 获取单条数据
  58. * @param entity
  59. * @return entity
  60. */
  61. public T getByEntity(T entity);
  62. /**
  63. * 查询数据列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page<T>(pageNo, pageSize));
  64. * @param entity
  65. * @return
  66. */
  67. public List<T> findList(T entity);
  68. /**
  69. * 查询数据总数
  70. * @param entity
  71. * @return
  72. */
  73. public long findCount(T entity);
  74. }

调用举例:

  1. // 查询一条,更新
  2. Employee employee = new Employee();
  3. employee.setEmpCode('E001');
  4. employee = employeeDao.get(employee);
  5. employee.setMobile('18666666666');
  6. employeeDao.update(employee);
  7. // 列表查询、统计
  8. Employee employee = new Employee();
  9. employee.setEmpName('小王');
  10. employee.setPage(new Page(1, 20)); // 分页查询
  11. List<Employee> list = employeeDao.findList(employee);
  12. Long count = employeeDao.findCount(employee);
  13. // 批量插入
  14. employeeDao.insertBatch(list);

是不是有种事半功倍的感觉,小小的配置,可以实现几乎可以完成原来需要写代码的80%时间。

也许你会觉着配置复杂,难以理解,只要你用上了相信你就会爱不释手。

还有一个惊喜,这些配置也可以通过代码生成工具快速生成,喜欢不喜欢。

嗯!基本增删改查,批量操作,按实体属性查询,按实体属性更新,以及统计都有了 ↓↓↓ 可是 ↓↓↓

日期范围查询

可是,这么多还是还不够,比如,我们想实现,日期范围查询怎么办?某个实体属性,实现双重查询(如那么既能eq又能like)怎么办?想实现or、is null,括号查询怎么办?这些都么关系,已经替你考虑了,如下:

  1. ////////// 日期范围查询,gte,lte ////////////////
  2. public Date getCreateDate_gte(){
  3. return sqlMap.getWhere().getValue("create_date", QueryType.GTE);
  4. }
  5. public void setCreateDate_gte(Date createDate){
  6. createDate = DateUtils.getOfDayFirst(createDate); // 将日期的时间改为0点0分0秒
  7. sqlMap.getWhere().and("create_date", QueryType.GTE, createDate);
  8. }
  9. public Date getCreateDate_lte(){
  10. return sqlMap.getWhere().getValue("create_date", QueryType.LTE);
  11. }
  12. public void setCreateDate_lte(Date createDate){
  13. createDate = DateUtils.getOfDayLast(createDate); // 将日期的时间改为23点59分59秒
  14. sqlMap.getWhere().and("create_date", QueryType.LTE, createDate);
  15. }

双重字段查询

  1. ////////// 双重字段查询,支持eq,支持like ////////////////
  2. public String getTableName() {
  3. return StringUtils.lowerCase(tableName);
  4. }
  5. public void setTableName(String tableName) {
  6. this.tableName = tableName;
  7. }
  8. public String getTableName_like() {
  9. return sqlMap.getWhere().getValue("table_name", QueryType.LIKE);
  10. }
  11. public void setTableName_like(String tableName) {
  12. sqlMap.getWhere().and("table_name", QueryType.LIKE, tableName);
  13. }

扩展括号查询

  1. ////////// 支持 or、is null,括号 ////////////////
  2. public String getParentTableName_isNull() {
  3. return this.getParentTableName();
  4. }
  5. public void setParentTableName_isNull(String parentTableName) {
  6. if (StringUtils.isBlank(parentTableName)){
  7. sqlMap.getWhere().andBracket("parent_table_name", QueryType.IS_NULL, null, 2)
  8. .or("parent_table_name", QueryType.EQ_FORCE, "", 3).endBracket();
  9. this.setParentTableName(null);
  10. }else{
  11. this.setParentTableName(parentTableName);
  12. }
  13. }

支持 IN 条件查询

  1. ////////// 支持 in、not in 条件查询 ////////////////
  2. public String[] getCategoryCode_in(){
  3. return sqlMap.getWhere().getValue("category_code", QueryType.IN);
  4. }
  5. public void setCategoryCode_in(String[] codes){
  6. sqlMap.getWhere().and("category_code", QueryType.IN, codes);
  7. }

扩展自定义列

还有一种情况,如所有的配置都配置好了,我只需要在sql返回值里加一个简单的统计数,多返回一列,你可以这样写:

  1. // 实体类定义
  2. @Table(name="${_prefix}gen_table", alias="a", columns={
  3. // @Column 。。。此处省略 。。。
  4. },
  5. // 扩展Column里指定一个Key名字,类里并定义一个需要返回的属性和get set
  6. extColumnKeys="extColumn"
  7. )
  8. public class GenTable extends DataEntity<GenTable> {
  9. private Long childNum; // 子表个数
  10. public Long getChildNum() {
  11. return childNum;
  12. }
  13. public void setChildNum(Long childNum) {
  14. this.childNum = childNum;
  15. }
  16. }
  17. // Service 里,通过sqlMap设置你刚定义的Key即可,如下
  18. public Page<GenTable> findPage(Page<GenTable> page, GenTable genTable) {
  19. // 添加扩展列,查询子表个数(子查询)
  20. String extColumn = "(SELECT count(1) FROM "+MapperHelper.getTableName(genTable)
  21. +" WHERE parent_table_name=a.table_name) AS \"childNum\"";
  22. genTable.getSqlMap().add("extColumn", extColumn);
  23. return super.findPage(page, genTable);
  24. }

多表联合查询

如果你的表里只存储了code编码,未存储name名称,你需要通过code来联合查询出name。但实体里联合查询的表不是以实体存在的,而定义在了当前实体中,这时候应该指定JoinTable的attrName为this,代表将数据映射到当前实体,举例如下:

  1. @Table(name="${_prefix}test", alias="a", columns={
  2. // 此处省略...
  3. @Column(name="test_code", attrName="testCode", label="编码(外键)"),
  4. },
  5. // 联合查询出外键编码的名称数据(attrName="this",指定this代表,当前实体)
  6. joinTable={
  7. @JoinTable(type=Type.LEFT_JOIN, entity=Test2.class, attrName="this", alias="b",
  8. on="b.code = a.test_code",
  9. columns={
  10. @Column(name="name", attrName="testName", label="名称"),
  11. }),
  12. },
  13. orderBy="a.update_date DESC"
  14. )
  15. public class Test extends DataEntity<Test> {
  16. private static final long serialVersionUID = 1L;
  17. // 此处省略...
  18. private String testCode; // 编码(外键,Test2关联表的主键)
  19. private String testName; // 名称(改属性是关联表字段,不是本表字段)
  20. /// 省略 get set 方法
  21. }

复杂语句查询

如果以上仍得不到你的满足,怎么办,那你可以写Mapper.xml了,比如EmployeeDao.xml一些通用的字段、条件,你就不需要在xml再写一遍了,你只需要补充SQL即可(相同id,如id=”findList”则会自动覆盖默认设置):

  1. <select id="findList" resultType="Employee">
  2. SELECT ${sqlMap.column.toSql('a')}
  3. FROM ${_prefix}sys_employee a
  4. <where>
  5. ${sqlMap.where.toSql('a')}
  6. </where>
  7. ORDER BY ${sqlMap.order.toSql('a')}
  8. </select>

覆写自带 Mapper 的语句

平台支持 mapper xml 的 select/update/delete 设置 weight 权重属性,指定相同的 key 权重高的优先加载,权重低的将被忽略(4.1.3+)。

例如,你想覆写自带的 UserUtils.getByLoginCode 查询语句如下:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.jeesite.modules.sys.dao.UserDao">
  4. <!-- 根据登录名查询用户(不区分大小写),指定 weight 即可覆写 -->
  5. <select id="getByLoginCode" resultType="User" weight="100">
  6. SELECT ${sqlMap.column.toSql()}
  7. FROM ${sqlMap.table.toSql()}
  8. WHERE a.status != #{STATUS_DELETE}
  9. AND upper(a.login_code) = upper(#{loginCode})
  10. </select>
  11. </mapper>

指定 typeHandler

有些情况可能需要复杂类型,这时候你就用到了 typeHandler 个性化类型:

  1. @Table(name="m_banner", alias="a", columns={
  2. @Column(name="bind_items", attrName="bindItems", label="绑定的数据", isQuery=false,
  3. javaType=java.util.List.class, typeHandler=JsonTypeHandler.class),
  4. }

以上方法适应于 “插入、更新、查询条件” 的参数类型设置,那么,如何给查询结果集指定 typeHeader?

你可以使用扩展 Mapper XML 来实现,如下:

  1. <resultMap type="com.jeesite.modules.banner.entity.Banner" id="bannerDetail">
  2. <result column="bindItems" property="bindItems"
  3. javaType="java.util.List" typeHandler="com.jeesite.common.JsonTypeHandler"/>
  4. </resultMap>
  5. <select id="get" resultMap="bannerDetail">
  6. SELECT ${sqlMap.column.toSql()}
  7. FROM ${sqlMap.table.toSql()}
  8. <where>
  9. ${sqlMap.where.toSql()}
  10. </where>
  11. ORDER BY ${sqlMap.order.toSql()}
  12. </select>

这样的Dao,你满意吗?编码原来如此简单,提高了效率,又不损失灵活,是不是很有趣呢。

附:API

@Table

  1. /**
  2. * 指定实体的物理表属性
  3. * @author ThinkGem
  4. */
  5. public @interface Table {
  6. /**
  7. * 物理表名
  8. */
  9. String name() default "";
  10. /**
  11. * 当前表别名
  12. */
  13. String alias() default "a";
  14. /**
  15. * 表列定义
  16. */
  17. Column[] columns();
  18. /**
  19. * 查询,关联表
  20. */
  21. JoinTable[] joinTable() default {};
  22. /**
  23. * 指定排序
  24. */
  25. String orderBy() default "";
  26. /**
  27. * 表说明
  28. */
  29. String comment() default "";
  30. /**
  31. * 扩展ColumnSQL,在这里指定sqlMap的key。<br>
  32. * 例如:\@Table(extColumnKeys="dataScopeColumn");<br>
  33. * Service里设置:sqlMap.put("extColumn", "column_name AS \"columnName\"");<br>
  34. * 在执行查询的时候,该语句放到自动会加到Select最后并执行。<br>
  35. * <b>注意:</b>如果设置,必须后台代码中设置,否则可能造成sql注入漏洞<br>
  36. */
  37. String extColumnKeys() default "";
  38. /**
  39. * 扩展FromSQL,在这里指定sqlMap的key。<br>
  40. * 例如:\@Table(extFromKeys="dataScopeFrom");<br>
  41. * Service里设置:sqlMap.put("dataScopeFrom", "JOIN table_name t on t.pk=a.pk");<br>
  42. * 在执行查询的时候,该语句放到自动会加到From最后并执行。<br>
  43. * <b>注意:</b>如果设置,必须后台代码中设置,否则可能造成sql注入漏洞<br>
  44. */
  45. String extFromKeys() default "";
  46. /**
  47. * 扩展WhereSQL,在这里指定sqlMap的key。<br>
  48. * 例如:\@Table(extWhereKeys="dataScopeWhere");<br>
  49. * Service里设置:sqlMap.put("dataScopeWhere", "AND column_name='value'");<br>
  50. * 在执行查询的时候,该语句放到自动会加到Where最后并执行。<br>
  51. * <b>注意:</b>如果设置,必须后台代码中设置,否则可能造成sql注入漏洞<br>
  52. */
  53. String extWhereKeys() default "";
  54. }

@Column

  1. /**
  2. * 定义物理表列属性(不继承父类注解)
  3. * @author ThinkGem
  4. */
  5. public @interface Column {
  6. /**
  7. * 字段名(例如:config_key)
  8. */
  9. String name() default "";
  10. /**
  11. * java类型 V4.0.6+
  12. */
  13. Class<?> javaType() default void.class;
  14. /**
  15. * jdbc类型 V4.0.6+
  16. */
  17. JdbcType jdbcType() default JdbcType.UNDEFINED;
  18. /**
  19. * 类型处理器注册器 V4.0.6+
  20. */
  21. Class<? extends TypeHandler<?>> typeHandler() default UnknownTypeHandler.class;
  22. /**
  23. * 属性名,若不指定,则根据name()字段名进行驼峰命名法转换(例如:config_key 转换为 configKey)
  24. */
  25. String attrName() default "";
  26. /**
  27. * 标签名
  28. */
  29. String label() default "";
  30. /**
  31. * 字段备注
  32. */
  33. String comment() default "";
  34. /**
  35. * 是否主键(update、delete时的条件)
  36. */
  37. boolean isPK() default false;
  38. /**
  39. * 是否插入字段
  40. */
  41. boolean isInsert() default true;
  42. /**
  43. * 是否更新字段
  44. */
  45. boolean isUpdate() default true;
  46. /**
  47. * 是否更新字段(强制更新)V4.0.5+
  48. */
  49. boolean isUpdateForce() default false;
  50. /**
  51. * 是否是查询字段
  52. */
  53. boolean isQuery() default true;
  54. /**
  55. * 查询类型
  56. */
  57. QueryType queryType() default QueryType.EQ;
  58. /**
  59. * 包含嵌入一个实体
  60. */
  61. Class<?> includeEntity() default Class.class;
  62. }

@JoinTable

  1. /**
  2. * 指定实体的物理表的关联表属性
  3. * @author ThinkGem
  4. */
  5. public @interface JoinTable {
  6. /**
  7. * 连接类型
  8. */
  9. Type type() default Type.JOIN;
  10. public enum Type{
  11. JOIN("JOIN"), // INNER JOIN
  12. LEFT_JOIN("LEFT JOIN"),
  13. RIGHT_JOIN("RIGHT JOIN");
  14. private final String value;
  15. Type(String value) { this.value = value; }
  16. public String value() { return this.value; }
  17. }
  18. /**
  19. * 连接的表,指定实体Class
  20. */
  21. Class<?> entity();
  22. /**
  23. * 当前表别名
  24. */
  25. String alias();
  26. /**
  27. * 连接表条件
  28. */
  29. String on();
  30. /**
  31. * 对应主表中对应的属性名,若不指定,则根据entity()进行首字母小写得到属性名(例如:Config 转换为 config)
  32. */
  33. String attrName() default "";
  34. /**
  35. * 连接表,返回的列,若不指定,则读取entity()的所有列。
  36. */
  37. Column[] columns() default {};
  38. }

QueryType

  1. /**
  2. * 查询类型
  3. * @author ThinkGem
  4. */
  5. public enum QueryType{
  6. EQ("="),
  7. NE("!="),
  8. GT(">"),
  9. GTE(">="),
  10. LT("<"),
  11. LTE("<="),
  12. IN("IN"), // 接受 Object[] 或 List 参数
  13. NOT_IN("NOT IN"),
  14. LIKE("LIKE", "%", "%"),
  15. LEFT_LIKE("LIKE", "%", ""),
  16. RIGHT_LIKE("LIKE", "", "%"),
  17. IS_NULL("IS NULL"),
  18. IS_NOT_NULL("IS NOT NULL"),
  19. // 强制条件,不管值是不是空字符串都加载这个查询条件
  20. EQ_FORCE("=", true),
  21. NE_FORCE("!=", true),
  22. ;
  23. }

多数据源

在 JeeSite 中使用多数据源是比较简单的,只需在配置文件中配置附加数据源即可,附加数据源同样支持其它类型数据库、连接池、用户名、密码加密等。

配置方法

  1. # 数据库连接
  2. jdbc:
  3. # Mysql 数据库配置(主数据源,必须保留)
  4. type: mysql
  5. driver: com.mysql.jdbc.Driver
  6. url: jdbc:mysql://127.0.0.1:3306/jeesite?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
  7. username: root
  8. password: 123456
  9. testSql: SELECT 1
  10. # 连接信息加密
  11. encrypt:
  12. # 加密连接用户名
  13. username: false
  14. # 加密连接密码
  15. password: true
  16. # 数据库连接池配置
  17. pool:
  18. # 初始化连接数
  19. init: 1
  20. # 最小连接数
  21. minIdle: 3
  22. # 最大连接数
  23. maxActive: 20
  24. # 多数据源名称列表,多个用逗号隔开,使用方法:@MyBatisDao(dataSourceName="ds2")
  25. dataSourceNames: ds2,ds3
  26. # 多数据源配置:ds2(附加数据源2)
  27. ds2:
  28. type: mysql
  29. driver: com.mysql.jdbc.Driver
  30. url: jdbc:mysql://127.0.0.1:3306/jeesite2?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
  31. username: root
  32. password: 123456
  33. testSql: SELECT 1
  34. encrypt:
  35. username: false
  36. password: true
  37. pool:
  38. init: 1
  39. minIdle: 3
  40. maxActive: 20
  41. # 多数据源配置:ds3(附加数据源3)
  42. ds3:
  43. type: oracle
  44. driver: oracle.jdbc.driver.OracleDriver
  45. url: jdbc:oracle:thin:@127.0.0.1:1521/orcl
  46. username: jeesite
  47. password: jeesite
  48. testSql: SELECT 1 FROM DUAL
  49. encrypt:
  50. username: false
  51. password: true
  52. pool:
  53. init: 1
  54. minIdle: 3
  55. maxActive: 20

注意:yml格式要求比较严格,注意缩进,前方空格个数。

使用方法:

1)静态分配数据源:

  1. @MyBatisDao(dataSourceName="ds2")
  2. public interface TestDataDao extends BaseDao {
  3. }
  1. @MyBatisDao(dataSourceName="ds3")
  2. public interface TestDataDao extends BaseDao {
  3. }

2)动态分配数据源:

dao:

  1. @MyBatisDao(dataSourceName=DataSourceHolder.EMPTY)
  2. public interface TestDataDao extends BaseDao {
  3. }

service:

  1. // 动态设置数据源
  2. DataSourceHolder.setDataSourceName(dataSourceName);
  3. // 恢复默认数据源
  4. DataSourceHolder.clearDataSourceName();