• 数据库中控制某一字段字符长度的应用



    在工作中遇到了这么一个场景:

    在数据库中需要对表的某个字段进行字符追加,并且字符追加在字段前端,对字符的长度有限制,

    例如:保持字段的长度在100以内,每次追加固定字符,在字段的前面,当字段超过100时,截掉超出的部分。

    根据实际的情况,我们提出了3种解决方案:

    1 实现一种queue,保持其中的容量固定,并最后序列化进数据库,当需要插入字符,从数据库中取出,反序列化,向queue中插入数据,

    并且当数据超过容量时自动截掉最先插入的数据,最后再将其序列化进入数据库;

    2 编写原生的mysql语句,对字符串进行操作;

    3 由于项目中采用JPA,因此找到一种jpql语句,与2实现功效相当。

    经过思考,比较了三种方案的优缺点:

    方案一:容易实现,java实现,通用性也不错,但是当插入字符串时,对数据库操作存在事务性,当并发操作时,会产生问题。

    方案二:采用一条sql语句实现,简单,没有事务性存在,不用考虑并发的问题,但是如果数据库更换,需要重写sql语句。

    方案三:采用标准的jpql语句实现,是一种标准,对于数据库更换不存在修改问题,没有事务性,不需要考虑并发问题。

    综上所述,采用第三种方案是最优的。

    在实验过程中,实现了方案一和方案三:

    方案一:

    用于存放字符串的queue

     1 import java.io.Serializable;
     2 import java.util.ArrayList;
     3 import java.util.LinkedList;
     4 import java.util.List;
     5
     6 public class StrsQueue implements Serializable {
     7
     8     /**
     9      *
    10      */
    11     private static final long serialVersionUID = -204264456311340382L;
    12
    13     private int totalSize;// 记录queue的容量
    14     private LinkedList<String> queue;
    15
    16     public StrsQueue (int totalSize) {
    17         queue = new LinkedList<String>();
    18         this.totalSize=totalSize;
    19     }
    20
    21    
    22
    23     public void addStr(String str) {
    24         queue.add(0, str);
    25         if (queue.size() > totalSize) {
    26             queue.removeLast();//超过容量,删掉最先插入的数据
    27         }
    28     }
    29
    30     public List<String> obtainStrs( int pageNumber,int pageSize) {
    31         int offset=(pageNumber-1)*pageSize;
    32         if (offset >= totalSize) {
    33             return null;
    34         }
    35         ArrayList<String> list = new ArrayList<String>();
    36         int length=Math.min(queue.size(), totalSize);
    37 //        int length = (queue.size() < totalSize) ? queue.size() : totalSize;
    38         if ((offset + pageNumber) > length || pageSize == 0) {
    39             for (int i = offset; i < length; i++) {
    40                 String feedId = (String) queue.get(i);
    41                 list.add(feedId);
    42             }
    43         } else {
    44             for (int i = offset; i < pageSize; i++) {
    45                 list.add((String) queue.get(i));
    46             }
    47         }
    48         return list;
    49     }
    50
    51 }

    使用StrQueue的Entity,

      2
      3 import java.io.ByteArrayInputStream;
      4 import java.io.ByteArrayOutputStream;
      5 import java.io.IOException;
      6 import java.io.ObjectInputStream;
      7 import java.io.ObjectOutputStream;
      8
      9 import javax.persistence.Column;
     10 import javax.persistence.Entity;
     11 import javax.persistence.Id;
     12 import javax.persistence.Table;
     13 import javax.persistence.Transient;
     14
     15
     16 /**
     17  * UserFeedInbox entity. @author MyEclipse Persistence Tools
     18  */
     19 @Entity
     20 @Table(name = "table_name", catalog = "database")
     21 public class UserFeedInboxEntry implements java.io.Serializable {
     22     // Fields
     23
     24    
     25     private static final long serialVersionUID = 840144016005162535L;
     26     private String id;
     27     private String userId;
     28     private String userType;
     29     private byte[] strs;
     30
     31     private StrsQueue strsQueue;
     32    
     33     // Constructors
     34
     35     /** default constructor */
     36     public UserFeedInboxEntry() {
     37     }
     38
     39     /** minimal constructor */
     40     public UserFeedInboxEntry(String id) {
     41         this.id = id;
     42     }
     43
     44     /** full constructor */
     45     public UserFeedInboxEntry(String id, String userId, String userType,
     46             byte[] strs) {
     47         this.id = id;
     48         this.userId = userId;
     49         this.userType = userType;
     50         this.strs = strs;
     51     }
     52
     53     // Property accessors
     54     @Id
     55     @Column(name = "id", unique = true, nullable = false, length = 36)
     56     public String getId() {
     57         return this.id;
     58     }
     59
     60     public void setId(String id) {
     61         this.id = id;
     62     }
     63
     64     @Column(name = "user_id", length = 36)
     65     public String getUserId() {
     66         return this.userId;
     67     }
     68
     69     public void setUserId(String userId) {
     70         this.userId = userId;
     71     }
     72
     73     @Column(name = "user_type", length = 50)
     74     public String getUserType() {
     75         return this.userType;
     76     }
     77
     78     public void setUserType(String userType) {
     79         this.userType = userType;
     80     }
     81
     82     @Column(name = "strs", columnDefinition = "blob")
     83     public byte[] getStrs() {
     84         return this.strs;
     85     }
     86
     87     public void setStrs(byte[] strs) {
     88         this.strs = strs;
     89
     90         ByteArrayInputStream bais;
     91         ObjectInputStream in;
     92         try {
     93             bais = new ByteArrayInputStream(strs);
     94             in = new ObjectInputStream(bais);
     95             strsQueue = (StrsQueue) in.readObject();
     96             in.close();
     97         } catch (IOException ex) {
     98             ex.printStackTrace();
     99         } catch (ClassNotFoundException ex) {
    100             ex.printStackTrace();
    101         }
    102     }
    103
    104     @Transient
    105     public StrsQueue getFeedsIdsQueue() {
    106         return strsQueue;
    107     }
    108
    109     public void setStrsQueue(StrsQueue strsQueue) {
    110         this.strsQueue = strsQueue;
    111         ByteArrayOutputStream baos;
    112         ObjectOutputStream out;
    113         baos = new ByteArrayOutputStream();
    114         try {
    115             out = new ObjectOutputStream(baos);
    116             out.writeObject(strsQueue);
    117             out.close();
    118         } catch (IOException e) {
    119             e.printStackTrace();
    120         }
    121         this.strs = baos.toByteArray();
    122     }
    123
    124 }


    注:开始时设计的Queue中,采用的底层实现是ArrayList,在queue中记录一个position变量,插入字符串时直接插入到arraylist的尾部,并将position指到当前位置,当queue的字符串的数量达到容量时,position指向arraylist的0位置,从头开始set值,这样能够保证容量不变,并且不需要对list进行删除操作,当初做这种设计是考虑当容量大时,用linkedlist虽然插入和删除动作对链表结构性能影响不大,但是如果从链表中取值的话需要遍历,如果取的值很多,并且取值的位置不固定时,linkedlist的取值效率没有arraylist直接根据下标取值的效率高,因此最初将底层设计为arraylist,但是最后跟头讨论了一下,本项目的queue的容量没有那么大,linkedlist取值的效率问题不需要考虑,因此改为采用linkedlist实现,代码比较清晰易懂。

    方案三:本项目采用spring data for jpa 实现,

     2
     3 import org.springframework.data.jpa.repository.Modifying;
     4 import org.springframework.data.jpa.repository.Query;
     5 import org.springframework.data.repository.CrudRepository;
     6 import org.springframework.data.repository.query.Param;
     7
     9
    10 public interface MyEntryJpaRepo extends CrudRepository<MyEntry, String> {


        //根据offset和length获取字符串
    28     @Query("SELECT SUBSTRING(m.strs,:offset, :length) FROM MyEntry m WHERE m.userId = :userId AND m.userType = :userType")
    29     public String obtainStrs(@Param("userId")String userId, @Param("userType")String userType,@Param("offset")int offset,@Param("length")int length);
    30    
    31     @Modifying
    32     @Query("UPDATE MyEntry m  SET m.strs = CONCAT(CONCAT(:str ,','),SUBSTRING(m.strs,1,:strsLength)) WHERE m.userId = :userId AND m.userType = :userType")
    33     public void addStrToInbox(@Param("userId")String userId, @Param("userType")String userType,@Param("str")String str,@Param("idsLength")int idsLength);
    34
    35 }


    最后做了单元测试,就不一一介绍了,但是测试时发现个问题,当spring data jpa中的offset为负值时,数据从字段的后面开始数并截取相应长度的字符串,当offset为0时,返回空串“”。

  • 相关阅读:
    一个openbsd的服务器,可以使用它的公网IP~
    深入浅出C++虚函数表
    C++函数的高级特性-函数重载
    《用TCP/IP进行网际互联》读书笔记
    C++中const的作用【转】
    C++学习继承中的作用域(10)
    ping 127.0.0.1与本机的IP有什么不同
    C++多态性:虚函数的调用原理
    mysql连接字段
    常用正则表达式
  • 原文地址:https://www.cnblogs.com/yanzhenxing/p/2673869.html
Copyright © 2020-2023  润新知