spring-data-jpa连接mycat实现应用的读写分离

主从复制

读写分离

本文介绍使用spring-data-jpa连接mycat实现应用的读写分离.

原文地址:spring-data-jpa连接mycat实现应用的读写分离

系统环境

  • spring-boot 1.4.3-RELEASE
  • jdk1.8

进入正题

application.yml配置文件

这个很传统,指定mysql以及datasource就可以.

特别说一句:mycat跟应用是相互独立的,mycat后边的mysql集群对于应用来说就相当于一台单独的mysql server,所以,不要纠结与应用该用什么数据库连接工具

spring:
  application:
    name: mycat-jpa
  datasource:
    platform: mysql
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:8066/mall?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
    username: root
    password: jiabin
  jpa:
    hibernate:
      ddl-auto: none
    show-sql: true

JpaTransactionConfig类文件

这个配置类是重点.

在使用mycat时需要关闭spring-data-jpa默认的事务管理机制.
原因如下:

  • mycat对于开启了事务的查询,插入等操作,都会走主库
  • spring-data-jpa默认的事务管理机制对查询操作执行的是只读事务,话说只读事务也是事务啊

鉴于以上两个原因.我们就得使用enableDefaultTransactions = false来关闭spring-data-jpa默认的事务管理机制.

好吧,既然我们关闭了默认的事务管理机制,我们就得使用@Transactional来开启声明式事务处理.哈哈,也就是说,我们需要用添加@Transactional注解的硬编码方式来实现事务管理.见SalesmanService

package jpa.mycat;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

/**
 * Created by ssab on 17-1-4.
 */
@EnableJpaRepositories(basePackages = "jpa.mycat", enableDefaultTransactions = false)
@Configuration
public class JpaTransactionConfig {
}

弄懂了这两个配置,剩下的就简单了.

Salesman实体类

package jpa.mycat;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

/**
 * Created by ssab on 17-1-5.
 */
@Entity
@Table(name = "salesman")
public class Salesman {
  @Id
  @GenericGenerator(name = "idgen", strategy = "increment")
  @GeneratedValue(generator = "idgen")
  @Column(name = "id")
  private Long id;//业务员ID

  private String userNum;//工号

  private String trueName;//真实姓名

  private String address;//地址

  private String avatarPicUrl;//头像的图片地址

  private String telephone;//固定电话:区号-号码

  private String mobile;//手机号码

  private int disabled;//是否作废0否1是

  private String remark;//备注

  private String appUserId;//备用userId字段(外勤APP用)

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUserNum() {
    return userNum;
  }

  public void setUserNum(String userNum) {
    this.userNum = userNum;
  }

  public String getTrueName() {
    return trueName;
  }

  public void setTrueName(String trueName) {
    this.trueName = trueName;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getAvatarPicUrl() {
    return avatarPicUrl;
  }

  public void setAvatarPicUrl(String avatarPicUrl) {
    this.avatarPicUrl = avatarPicUrl;
  }

  public String getTelephone() {
    return telephone;
  }

  public void setTelephone(String telephone) {
    this.telephone = telephone;
  }

  public String getMobile() {
    return mobile;
  }

  public void setMobile(String mobile) {
    this.mobile = mobile;
  }

  public int getDisabled() {
    return disabled;
  }

  public void setDisabled(int disabled) {
    this.disabled = disabled;
  }

  public String getRemark() {
    return remark;
  }

  public void setRemark(String remark) {
    this.remark = remark;
  }

  public String getAppUserId() {
    return appUserId;
  }

  public void setAppUserId(String appUserId) {
    this.appUserId = appUserId;
  }

  @Override
  public String toString() {
    return "Salesman{" +
        "id=" + id +
        ", userNum='" + userNum + '\'' +
        ", trueName='" + trueName + '\'' +
        ", address='" + address + '\'' +
        ", avatarPicUrl='" + avatarPicUrl + '\'' +
        ", telephone='" + telephone + '\'' +
        ", mobile='" + mobile + '\'' +
        ", disabled=" + disabled +
        ", remark='" + remark + '\'' +
        ", appUserId='" + appUserId + '\'' +
        '}';
  }
}

SalesmanRepository

package jpa.mycat;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
 * Created by ssab on 17-1-5.
 */
public interface SalesmanRepository extends JpaRepository<Salesman, Long> {
  Salesman save(Salesman salesman);

  @Query(value = "select * from salesman limit 0,18", nativeQuery = true)
  List findAll();
}

SalesmanService

package jpa.mycat;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by ssab on 17-1-5.
 */
@Service
public class SalesmanService {

  @Autowired
  private SalesmanRepository repository;

  @Transactional(propagation = Propagation.REQUIRED)
  public Salesman save(Salesman salesman) {
    return repository.save(salesman);
  }

  @Transactional(propagation = Propagation.NOT_SUPPORTED)
  public List findAll() {
    return repository.findAll();
  }

}

测试

SalesmanServiceTest

package jpa.mycat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * Created by ssab on 17-1-5.
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class SalesmanServiceTest {
  @Autowired
  private SalesmanService service;

  @Test
  public void testFindAll() {
    service.findAll().forEach(salesman -> System.out.println(salesman.toString()));
  }

  @Test
  public void testSave(){
    Salesman salesman = new Salesman();

    salesman.setUserNum("3333333");
    salesman.setTrueName("ssab");
    salesman.setAddress("山东省莱芜市");
    salesman.setMobile("152222222");
    salesman.setDisabled(0);

    service.save(salesman);
  }
}

运行testFindAll方法,查看mycat日志

testfindall

注意看图中红框内的内容

好吧我们确定是走的从库.

运行testSave方法,查看mycat日志

testsave

从图中红框内的内容我们发现走的是主库.

总结

使用spring-data-jpa连接mycat的重点就在于关闭spring-data-jpa的默认事务管理机制并使用@Transactional注解来进行声明式事务管理.

注意这点就可以了.

代码

spring-boot-jpa连接mycat实现读写分离

你可能感兴趣的:(java)