springboot-數(shù)據(jù)庫

數(shù)據(jù)庫

[toc]

MySQL

  • 準(zhǔn)備工作,加入數(shù)據(jù)庫的配置和依賴

    為了使用 jpamysql绿渣,在 pom.xml文件中增加依賴污尉。

    <!--jpa-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    <!--mysql-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    

    application.yml 配置 mysql 連接信息

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8
        username: root
        password: root
    
    # jpa
      jpa:
        database: MYSQL
        show-sql: true
    # Hibernate ddl auto (validate|create|create-drop|update)
        hibernate:
          ddl-auto: update
          naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
        properties:
          hibernate:
            dialect: org.hibernate.dialect.MySQL5Dialect
    

    Person.java

    @Entity
    public class Person {
    
        @Id
        @GeneratedValue
        private Integer id;
        private String name;
        private Integer age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    

    創(chuàng)建接口繼承JpaRepository,泛型使用的是

    public interface PersonRespository extends JpaRepository<Person, Integer> {
    }
    
  • 單表簡單查詢

    HelloController.java

    @RestController
    public class HelloController {
    
        @Autowired
        private PersonRespository personRespository;
    
        @PostMapping(value = "/addPerson")
        public Person addPerson(@RequestParam(value = "name") String name, @RequestParam(value = "age") Integer age) {
            Person person = new Person();
            person.setName(name);
            person.setAge(age);
            return personRespository.save(person);
        }
        
            @DeleteMapping(value = "/delPerson/{id}")
        public void delPerson(@PathVariable(value = "id") Integer id) {
            personRespository.delete(id);
        }
    
        @PutMapping(value = "/updatePerson")
        public Person updatePerson(@RequestParam(value = "id") Integer id, @RequestParam(value = "name") String name, @RequestParam(value = "age") Integer age) {
            Person person = new Person();
            person.setId(id);
            person.setName(name);
            person.setAge(age);
            return personRespository.save(person);
        }
    
        @GetMapping(value = "/findPerson/{id}")
        public Person findPerson(@PathVariable(value = "id") Integer id) {
            return personRespository.findOne(id);
        }
    
        @GetMapping(value = "/findPersons")
        public List<Person> findPerson() {
            return personRespository.findAll();
        }
    }
    
  • 單表根據(jù)年齡查詢

    PersonRespository.java

    增加一個根據(jù)年齡查詢的抽象方法

    public interface PersonRespository extends JpaRepository<Person, Integer> {
        Person findByAge(Integer age);
    }
    

    HelloController.java

    @RestController
    public class HelloController {
    
        @Autowired
        private PersonRespository personRespository;
    
        @GetMapping(value = "/findPersonByAge/{age}")
        public Person findPersonByAge(@PathVariable(value = "age") Integer age) {
            return personRespository.findByAge(age);
        }
    }
    



集成 Redis

pom.xml

<!--redis-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>
<!--gson-->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.2.4</version>
</dependency>

RedisTemplate.java Redis 配置

/**
 * RedisTemplate 初始化
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

application.yml 配置 redis 連接信息

spring:

# redis 配置迹辐,沒有密碼的話枪孩,可以不寫 password 或者 password 值不填寫
  redis:
    host: 192.168.18.130
    port: 6379
    pool:
      max-idle: 8
      min-idle: 0
      max-active: 8
      max-wait: -1

UserRedis.java 用戶模塊的 redis 增刪改查

@Repository
public class UserRedis {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    public void add(String key, Long time, User user) {
        Gson gson = new Gson();
        redisTemplate.opsForValue().set(key, gson.toJson(user), time, TimeUnit.MINUTES);
    }

    public void add(String key, Long time, List<User> users) {
        Gson gson = new Gson();
        redisTemplate.opsForValue().set(key, gson.toJson(users), time, TimeUnit.MINUTES);
    }


    public User get(String key) {
        Gson gson = new Gson();
        User user = null;
        String json = redisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(json))
            user = gson.fromJson(json, User.class);
        return user;
    }

    public List<User> getList(String key) {
        Gson gson = new Gson();
        List<User> ts = null;
        String listJson = redisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(listJson))
            ts = gson.fromJson(listJson, new TypeToken<List<User>>() {
            }.getType());
        return ts;
    }

    public void delete(String key) {
        redisTemplate.opsForValue().getOperations().delete(key);
    }
}

RedisController.java 接口類測試

@RestController
@RequestMapping(value = "/springboot")
public class RedisController {


    private static Logger logger = LoggerFactory.getLogger(RedisController.class);

    @Autowired
    UserRedis userRedis;

    @Autowired
    RoleService roleService;

    @RequestMapping(value = "/getRedis")
    public void getRedis() {
        Department deparment = new Department();
        deparment.setName("開發(fā)部");

        Role role = new Role();
        role.setName("admin");

        User user = new User();
        user.setName("user");
        user.setCreatedate(new Date());
        user.setDeparment(deparment);

        List<Role> roles = new ArrayList<>();
        roles.add(role);

        user.setRoles(roles);

        userRedis.delete(this.getClass().getName() + ":userByname:" + user.getName());
        userRedis.add(this.getClass().getName() + ":userByname:" + user.getName(), 10L, user);

        User userRes = userRedis.get(this.getClass().getName() + ":userByname:user");
        Assert.notNull(userRes);
        logger.info("======userRes====== name:{}, deparment:{}, role:{}",
                userRes.getName(), userRes.getDeparment().getName(), userRes.getRoles().get(0).getName());
    }

    @RequestMapping(value = "/springcache_redis_create")
    public Role springcache_redis_create() {
        Role role = new Role();
        role.setName("jack");
        return roleService.create(role);
    }

    @RequestMapping(value = "/springcache_redis_find/{id}", method = RequestMethod.GET)
    public Role springcache_redis_find(@PathVariable(value = "id") Long id) {
        return roleService.findById(id);
    }

    @RequestMapping(value = "/springcache_redis_update/{id}", method = RequestMethod.GET)
    public Role springcache_redis_update(@PathVariable(value = "id") Long id) {
        Role role = roleService.findById(id);
        role.setName("rose");
        return roleService.update(role);
    }

    @RequestMapping(value = "/springcache_redis_delete/{id}", method = RequestMethod.GET)
    public void springcache_redis_delete(@PathVariable(value = "id") Long id) {
        roleService.delete(id);
    }
}



Redis 緩存優(yōu)化

Spring Cache 注解

結(jié)構(gòu)簡單的對象憔晒,即沒有包含其他對象的實體,可以用 spring cache 的方式使用 redis 緩存蔑舞,前提是打開 spring cache拒担。

  • Spring Cache 配置

    /**
     * 結(jié)構(gòu)簡單的對象,既沒有包含其他對象的實體攻询,可以用 spring cache 的方式使用 redis 緩存
     * 前提是打開 spring cache
     */
    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport {
    
        @Bean
        public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
            StringRedisTemplate template = new StringRedisTemplate(factory);
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            template.setValueSerializer(jackson2JsonRedisSerializer);
            template.afterPropertiesSet();
            return template;
        }
    
        /**
         * Spring Cache 配置
         * @param redisTemplate
         * @return
         */
        @Bean
        public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
            RedisCacheManager manager = new RedisCacheManager(redisTemplate);
            manager.setDefaultExpiration(43200);//12小時
            return manager;
        }
    
        /**
         * simpleKey 根據(jù) 類名+參數(shù) id 作為唯一標(biāo)識
         * @Cacheable 存取緩存
         * @CachePut 更新緩存
         * @CacheEvict 刪除緩存
         * 注解中的 value 參數(shù)是一個 key 的前綴从撼,
         * 并由 keyGenerator 按照一定的規(guī)則生成一個唯一的標(biāo)識
         */
        @Bean
        public KeyGenerator simpleKey() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(target.getClass().getName() + ":");
                    for (Object obj : params) {
                        sb.append(obj.toString());
                    }
                    return sb.toString();
                }
            };
        }
    
        /**
         * objectId 根據(jù) 類名+參數(shù) id 作為唯一標(biāo)識
         * @Cacheable 存取緩存
         * @CachePut 更新緩存
         * @CacheEvict 刪除緩存
         * 注解中的 value 參數(shù)是一個 key 的前綴,
         * 并由 keyGenerator 按照一定的規(guī)則生成一個唯一的標(biāo)識
         */
        @Bean
        public KeyGenerator objectId() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(target.getClass().getName() + ":");
                    try {
                        sb.append(params[0].getClass().getMethod("getId", null).invoke(params[0], null).toString());
                    } catch (NoSuchMethodException no) {
                        no.printStackTrace();
                    } catch (IllegalAccessException il) {
                        il.printStackTrace();
                    } catch (InvocationTargetException iv) {
                        iv.printStackTrace();
                    }
                    return sb.toString();
                }
            };
        }
    }
    

    RoleService.java 使用 Spring Cache 注解來用 redis 操作钧栖。

    @Service
    public class RoleService {
        @Autowired
        private RoleRepository roleRepository;
    
        /**
         * @Cacheable(value = "mysql:findById:role", keyGenerator = "simpleKey")
         * value = "mysql:findById:role" 是一個key 的前綴低零,并由 keyGenerator 按照一定的規(guī)則生成一個唯一的標(biāo)識
         * @Cacheable 存取緩存
         * @CachePut 更新緩存
         * @CacheEvict 刪除緩存
         */
    
        @Cacheable(value = "mysql:findById:role", keyGenerator = "simpleKey")
        public Role findById(Long id) {
            return roleRepository.findOne(id);
        }
    
        @CachePut(value = "mysql:findById:role", keyGenerator = "objectId")
        public Role create(Role role) {
            return roleRepository.save(role);
        }
    
        @CachePut(value = "mysql:findById:role", keyGenerator = "objectId")
        public Role update(Role role) {
            return roleRepository.save(role);
        }
    
        @CacheEvict(value = "mysql:findById:role", keyGenerator = "simpleKey")
        public void delete(Long id) {
            roleRepository.delete(id);
        }
    }
    
  • 使用 Redis Template,配置可以參考第2章的RedisConfig.java

    @Repository
    public class UserRedis {
    
        @Autowired
        private RedisTemplate<String, String> redisTemplate;
    
    
        public void add(String key, Long time, User user) {
            Gson gson = new Gson();
            redisTemplate.opsForValue().set(key, gson.toJson(user), time, TimeUnit.MINUTES);
        }
    
        public void add(String key, Long time, List<User> users) {
            Gson gson = new Gson();
            redisTemplate.opsForValue().set(key, gson.toJson(users), time, TimeUnit.MINUTES);
        }
    
    
        public User get(String key) {
            Gson gson = new Gson();
            User user = null;
            String json = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(json))
                user = gson.fromJson(json, User.class);
            return user;
        }
    
        public List<User> getList(String key) {
            Gson gson = new Gson();
            List<User> ts = null;
            String listJson = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(listJson))
                ts = gson.fromJson(listJson, new TypeToken<List<User>>() {
                }.getType());
            return ts;
        }
    
        public void delete(String key) {
            redisTemplate.opsForValue().getOperations().delete(key);
        }
    }
    

    UserService.java 存儲和查詢策略拯杠,先查詢 redis掏婶,不存在再查詢數(shù)據(jù)庫同時添加到 redis

    /**
     * 先查詢 redis,不存在再查詢數(shù)據(jù)庫同時添加到 redis
     */
    @Service
    public class UserService {
        @Autowired
        private UserRepository userRepository;
        @Autowired
        private UserRedis userRedis;
        private static final String keyHead = "mysql:get:user:";
    
        public User findById(Long id) {
            User user = userRedis.get(keyHead + id);
            if (user == null) {
                user = userRepository.findOne(id);
                if (user != null)
                    userRedis.add(keyHead + id, 30L, user);
            }
            return user;
        }
    
        public User create(User user) {
            User newUser = userRepository.save(user);
            if (newUser != null)
                userRedis.add(keyHead + newUser.getId(), 30L, newUser);
            return newUser;
        }
    
        public User update(User user) {
            if (user != null) {
                userRedis.delete(keyHead + user.getId());
                userRedis.add(keyHead + user.getId(), 30L, user);
            }
            return userRepository.save(user);
        }
    
        public void delete(Long id) {
            userRedis.delete(keyHead + id);
            userRepository.delete(id);
        }
    
    }
    



提高數(shù)據(jù)庫訪問性能

Druid

pom.xml 增加 druid 依賴

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.0.9</version>
</dependency>
server:
  port: 8080
  tomcat:
    uri-encoding: utf-8
spring:
#系統(tǒng)默認(rèn)的 DataSource
#  datasource:
#    url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8
#    username: root
#    password: root

#阿里的 DruidDataSourc
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8
    username: root
    password: 12345678
    # 初始化大小潭陪,最小雄妥,最大
    initialSize: 5
    minIdle: 5
    maxActive: 20
    # 配置獲取連接等待超時的時間
    maxWait: 60000
    # 配置間隔多久才進行一次檢測,檢測需要關(guān)閉的空閑連接依溯,單位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一個連接在池中最小生存的時間老厌,單位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打開PSCache,并且指定每個連接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置監(jiān)控統(tǒng)計攔截的filters黎炉,去掉后監(jiān)控界面sql無法統(tǒng)計枝秤,'wall'用于防火墻
    filters: stat,wall,log4j
    # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    # 合并多個DruidDataSource的監(jiān)控數(shù)據(jù)
    #useGlobalDataSourceStat=true

  # jpa
  jpa:
    database: MYSQL
    show-sql: true
  #Hibernate ddl auto (validate|create|create-drop|update)
    hibernate:
      ddl-auto: update
      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect

  # redis 配置慷嗜,沒有密碼的話淀弹,可以不寫 password 或者 password 值不填寫
  redis:
    host: 192.168.18.130
    port: 6379
    password:
    pool:
      max-idle: 8
      min-idle: 0
      max-active: 8
      max-wait: -1



事務(wù)管理

在方法名稱上增加@Transactional若贮,該方法就有事務(wù)管理了。

@Service
public class PersonService {

    @Autowired
    private PersonRespository personRespository;

    @Transactional
    public void insertTwo() {
        Person person = new Person();
        person.setName("jack");
        person.setAge(40);
        personRespository.save(person);

        Person person1 = new Person();
        person1.setName("rose");
        person1.setAge(30000);
        int a = 1 / 0;
        personRespository.save(person1);

    }
}



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盲憎,一起剝皮案震驚了整個濱河市毯欣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饺鹃,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忿峻,居然都是意外死亡薄啥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門逛尚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垄惧,“玉大人,你說我怎么就攤上這事绰寞〉窖罚” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵滤钱,是天一觀的道長觉壶。 經(jīng)常有香客問我,道長件缸,這世上最難降的妖魔是什么铜靶? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮他炊,結(jié)果婚禮上争剿,老公的妹妹穿的比我還像新娘。我一直安慰自己痊末,他們只是感情好蚕苇,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著舌胶,像睡著了一般捆蜀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幔嫂,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天辆它,我揣著相機與錄音,去河邊找鬼履恩。 笑死锰茉,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的切心。 我是一名探鬼主播飒筑,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绽昏!你這毒婦竟也來了协屡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤全谤,失蹤者是張志新(化名)和其女友劉穎肤晓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡补憾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年漫萄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盈匾。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡腾务,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出削饵,到底是詐尸還是另有隱情岩瘦,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布葵孤,位于F島的核電站担钮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尤仍。R本人自食惡果不足惜箫津,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宰啦。 院中可真熱鬧苏遥,春花似錦、人聲如沸赡模。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漓柑。三九已至教硫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辆布,已是汗流浹背瞬矩。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锋玲,地道東北人景用。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像惭蹂,于是被迫代替她去往敵國和親伞插。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理盾碗,服務(wù)發(fā)現(xiàn)媚污,斷路器,智...
    卡卡羅2017閱讀 134,715評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法廷雅,類相關(guān)的語法耗美,內(nèi)部類的語法氢伟,繼承相關(guān)的語法,異常的語法幽歼,線程的語...
    子非魚_t_閱讀 31,665評論 18 399
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,815評論 0 11
  • 第6章 Spring Boot數(shù)據(jù)庫層集成 6.1 Spring Boot集成mybatis 在SpringBoo...
    光劍書架上的書閱讀 1,026評論 0 9
  • (一) 記得高中階段,同學(xué)WJL數(shù)學(xué)成績很好谬盐,幾乎次次滿分甸私,我則逢數(shù)學(xué)考試不佳。 向他取經(jīng)時飞傀,他很誠懇地說: 其實...
    偷影子的人Renaissanc閱讀 233評論 0 4