How to design database tables efficiently in Mysql - mysql

I have the following pojo
public class Like {
private Long commentId;
private Collection<Long> accountIds;
}
public class Comment {
private Long personId;
private Long pageId;
private Long Id;
private String text;
private Like like;
private LocalDate commentDate;
}
public class Page {
private Long Id;
private Long textId;
private Collection<Comment> comments;
private LocalTime postingDate;
private ViewType type;
private String mediaUrl;
private Collection<Long> openAccountIds;
private Like like;
}
public class Text{
private Long accountId;
private Long Id;
private String name;
private LocalTime firstPostedTime;
private LocalTime lastPostedTime;
private ViewType type;
private Collection<Page> pages;
private Like like;
private String description;
private Collection<Long> openAccountIds;
}
Now i have my text repository as follows:
public interface TextRepository {
Collection<Text> getAllTexts(Long accountId);
Diary getText(Long TextId);
Page getPage(Long pageId);
Comment getComment(Long commentId);
void addPageToText(Long TextId , Page page);
void addCommentToPage(Long pageId , Comment comment);
void updateText(Text text);
void deletePage(Long pageId);
void deleteComment(Long commentId);
void updateLikeToText(Long textIds);
void updateLikeToPage(Long pageId);
void updateLikeToComment(Long commentId);
}
I am a new bie to mysql. I wanted to know how to efficiently create mysql tables so i can retrieve the data in less possible time. Also if my pojo's contains any flaw in structure go ahead to change them or provide suggestions.

Here are some suggestions for the object model to consider (see comments),
// Specifying all the fields as private will not allow
// any other class to use the data!
public class Account
{
public String name;
public String location;
}
public class Text
{
public Collection<Account> likedBy;
public Collection<Account> openAccounts;
public Collection<Page> pages;
public Account postedBy;
public String name; // Not sure what this field represents...
public LocalTime firstPostedTime;
public LocalTime lastPostedTime;
public ViewType type;
public String description;
// Consider using get/set methods for collections,
// so as to expose only minimal required information
// public like(Account account)
// {
// likedBy.add(account);
// }
//
// public dislike(Account account)
// {
// likedBy.remove(account);
// }
}
public class Page
{
public Collection<Comment> comments;
public LocalTime postingDate;
public ViewType type;
public String mediaUrl;
public Collection<Account> openAccounts;
public Collection<Account> likedBy;
// public addComment(Comment comment)
// {
// ...
// Update posting date
// }
//
// public addOpenAccount(Account account)
// {
// ...
// }
}
public class Comment
{
public Account postedBy;
public String text;
public Collection<Account> likedBy;
public LocalDate commentDate;
}
The next step would be to construct an entity-relationship diagram. The primary keys and foreign keys (xxxId) are introduced while normalizing the schema.
The schema could look like this,
Account [id, name, location]
ViewType [id, description]
Comment [id, posted_by_account_id, text, postedDate]
CommentLikes [comment_id, account_id]
Text [id, account_id, name, firstPostedTime, lastPostedTime, type_Id, description]
TextAccounts [text_id, account_id]
TextLikes [text_id, account_id]
TextPages [text_id, page_id]
Page [id, mediaUrl, type_id, postingDate]
PageLikes [page_id, account_id]
PageComments [page_id, comment_id]
PageAccounts [page_id, account_id]

Related

Mocking static methods objects with Mockito/powermock

I have a class DistributionRule class which contains private Set distributions;
#Getter
#Setter
public class DistributionRule extends BaseModel {
private String ruleName;
private String skuId;
private String catalogueId;
private String categoryId;
private Boolean active;
private RuleLevel level;
private Set<Distribution> distributions;
private Double thresholdValue;
private RuleType ruleType = RuleType.GENERAL;
#Getter
#Setter
public static class Distribution {
private String consumerId;
private Double distribution;
}
}
In RuleServiceImpl, there is a method to get DistributionRule list:
#Override
public List<DistributionRule> getDistributionRules() {
return ruleRepository.findAll();
}
In DivRuleApplicationTests class:
#RunWith(SpringRunner.class)
#SpringBootTest
class DivRuleApplicationTests {
#Autowired
private RuleServiceImpl ruleServiceImpl;
#MockBean
RuleRepository ruleRepository;
#Test
void test() {
assertTrue(true);
}
#Test
public void getDistributionRulesTest(){
Set<Distribution> distributions = new HashSet();
when(ruleRepository.findAll()).thenReturn(Stream
.of(new DistributionRule("rule0010", "0010", " ", " ", true, "SKU", ""),
new DistributionRule("rule0020", "0020", "", "", true, "SKU", ""))
.collect(Collectors.toList()));
assertEquals(2, ruleServiceImpl.getDistributionRules().size());
}
}
How do I pass the "Distribution" values in Stream.of()?
Firstly, the method you are trying to mock on when, returns a List<DistributionRule>. In this case, you don't need to create a Stream.of(new DistributionRule(...)) and then collect it as a List. Simply use List.of(new DistributionRule(...)), as it will return the List you want it.
Secondly, you should annotate both DistributionRule and inner class Distribution with #AllArgsConstructor to generate a constructor with all arguments. This will let you create an DistributionRule object passing the Distribution Set as a parameter:
#Test
public void getDistributionRulesTest(){
Set<Distribution> distributions1 = Set.of(
new Distribution(...), new Distribution(...)
);
Set<Distribution> distributions2 = Set.of(
new Distribution(...), new Distribution(...)
);
when(ruleRepository.findAll()).thenReturn(List.of(
new DistributionRule("rule0010", "0010", ..., distributions1, ..),
new DistributionRule("rule0020", "0020", ..., distributions2, ...)
));
assertEquals(2, ruleServiceImpl.getDistributionRules().size());
}
PS: I usually use the #Data annotation instead of #Getter and #Setter, as it's a shortcut for that and other annotations. You can take a look here if you want to know more: https://projectlombok.org/features/Data

How to create json annotated POJO class

I see some class like this in the code I am looking, and wonder how
it was generated, they looks like generated by a plugin or by eclipse itself, I know eclipse can create a POJO file for your through wizard, but how do I get results like below?
public class Item implements Serializable{
private static final long serialVersionUID = 3868244754652312286L;
#JsonProperty("name")
private String name;
#JsonProperty("quantity")
private String quantity;
#JsonProperty("price")
private String price;
#JsonProperty("tax")
private String tax;
#JsonProperty("sku")
private String sku;
#JsonProperty("originalPrice")
private String originalPrice;
#JsonIgnore
private HashMap<String, Object> additionalProperties = new HashMap<>();
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}

Modifying objects list fileds saved as LONGBLOB in MySQL

I have a table "Project" in my MySQL Databse that contains an ArrayList saved as LONGBLOB (FiledDetailsData).
public class ProjectEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String projectName;
private String city;
private int nbFields;
private List<FiledDetailsData> FiledDetails;...
I already have alot of data saved and would like to keep it. The problem is that I had to change to structure of FiledDetailsData to add new fields
I've changed it from
#Embeddable
#XmlRootEllement
public class FiledDetailsData implements Serializable`{
private String id;
private String lot;
private String number;
private String street;
private String size;
private String status;
to
#Embeddable
#XmlRootEllement
public class FiledDetailsData implements Serializable`{
private String id;
private String lot;
private String number;
private String street;
private String size;
private String status;
private BigDecimal extraField;
private BigDecimal extraParking;
When I try to run the application with the previous data, I get this error
Could not deserialize object from byte array. Internal Exception: local class incompatible
I can fin it by deleting the LONGBLOB in my DAtaBase and recreating it, but then I lose all my data.
here are my save/edit methods
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
Thank you.

object convert to json how to modify the property key?

i have a json like
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"time":"16:05",
"temp":"11",
"WD":"北风",
"WS":"2级",
"SD":"27%",
"weather1":"晴"
}
and my class is
public class WeatherVO implements Serializable{
private static final long serialVersionUID = 2348480036959754071L;
#JsonProperty(value="weatherinfo")
private WeatherInfoVO weatherInfoVO;
#JsonIgnoreProperties(ignoreUnknown=true)
public class WeatherInfoVO{
//城市
#JsonProperty(value="city")
private String city;
//发布日期
private String publishDate;
//发布时间
#JsonProperty(value="time")
private String publishTime;
//星期
private String week;
//温度范围
private String tempRange;
//当前时刻温度
#JsonProperty(value="temp")
private String currentTemp;
//风向
#JsonProperty(value="WD")
private String windDirection;
//风力
#JsonProperty(value="WS")
private String windForce;
//当前时刻湿度
#JsonProperty(value="SD")
private String currentHumidity;
//体感温度
private String feelTemp;
//天气描述
private String weatherDesc;
}
}
i want to convert json to object like:
WeatherVO weatherVO = objectMapper.readValue (jsonString, WeatherVO.class);
and i want to return json use org.springframework.http.converter.json.MappingJacksonHttpMessageConverter class
and the return json is
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"time":"16:05",
"temp":"11",
"WD":"北风",
"WS":"2级",
"SD":"27%",
"weather1":"晴"
}
but i want to return like
"weatherInfo":{
"city":"北京",
"publishDate":"2014年3月4日",
"week":"星期二",
"tempRange":"8℃~-3℃",
"feelTemp":"10",
"publishTime":"16:05",
"currentTemp":"11",
"windDirection":"北风",
"windForce":"2级",
"currentHumidity":"27%",
"weather":"晴"
}
how can i do that?
thanks for your any suggestion and help.
You can achieve this by marking the getter of the field by #JsonIgnore then create another method that get the field and mark it as #JsonProperty.
My advice is to rename first your fields to avoid confusion. I renamed it like the json you have. So for example.
public class WeatherInfoVO{
private String city;
private String publishDate;
private String week;
private String tempRange;
private String feelTemp;
private String time;
private String temp;
private String WD;
private String WS;
private String SD;
private String weather1;
//getters and setters
}
then in you setters method mark the appropriate #JsonProperty.
#JsonProperty(value="time")
public void setTime(String time) {
this.temp = temp;
}
#JsonProperty(value="temp")
public void setTemp(String temp) {
this.temp = temp;
}
#JsonProperty(value="WD")
public void setWD(String WD) {
this.WD = WD;
}
#JsonProperty(value="WS")
public void setWS(String WS) {
this.WS = WS;
}
#JsonProperty(value="SD")
public void setSD(String SD) {
this.SD = SD;
}
#JsonProperty(value="weather1")
public void setWeather1(String weather1) {
this.weather1 = weather1;
}
//other setters here
and in your getters, make sure to add #JsonIgnore to the fields you want to rename. Since you declare it as #JsonIgnore, you need to create another getter and mark it as #JsonProperty. Do it only to the fields you are going to rename, in your case the fields are time, temp, WD, WS, SD and weather1 only. Here's an example.
#JsonIgnore
public void getTime(){
return time;
}
#JsonProperty(value="publishTime")
public void getPublishTime(){
return time;
}
#JsonIgnore
public void getTemp(){
return temp;
}
#JsonProperty(value="currentTemp")
public void getCurrentTemp(){
return temp;
}
#JsonIgnore
public void getWD(){
return WD;
}
#JsonProperty(value="windDirection")
public void getWindDirection(){
return WD;
}
#JsonIgnore
public void getWS(){
return WS;
}
#JsonProperty(value="windForce")
public void getWindForce(){
return WS;
}
#JsonIgnore
public void getSD(){
return SD;
}
#JsonProperty(value="currentHumidity")
public void getCurrentHumidity(){
return SD;
}
#JsonIgnore
public void getWeather1(){
return weather1;
}
#JsonProperty(value="weather")
public void getWeather(){
return weather1;
}

DAO MVC: why my class is NOT POJO

I use DAO MVC, and I after some googling I consider to store some variables as Enum in java and String in MySQL. So I create in Item.java (that will be persist into Item table) static initialization and static methods to convert Enum into String and vise versa.
But someone said me that after this static initialization and static methods my Item.java class became NOT POJO.
Question:
Why it became NOT POJO?
And if I'll make those methods not static Item.java class will be POJO?
EDITED: MY code:
package model;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
public class Order {
public enum OrderStatus {
NOT_REVIEWED,
APPROVED,
REJECTED,
RETURNED
}
// ==================
// = Transient =
// ==================
private static final Map<String, OrderStatus> convertStringToOrderStatusMap = new HashMap<String, OrderStatus>(3);
private static final Map<OrderStatus, String> convertOrderStatusToStringMap = new EnumMap<OrderStatus, String>(OrderStatus.class);
static {
convertStringToOrderStatusMap.put("not reviewed", OrderStatus.NOT_REVIEWED);
convertStringToOrderStatusMap.put("approved", OrderStatus.APPROVED);
convertStringToOrderStatusMap.put("rejected", OrderStatus.REJECTED);
convertStringToOrderStatusMap.put("returned", OrderStatus.RETURNED);
convertOrderStatusToStringMap.put(OrderStatus.NOT_REVIEWED, "not reviewed");
convertOrderStatusToStringMap.put(OrderStatus.APPROVED, "approved");
convertOrderStatusToStringMap.put(OrderStatus.REJECTED, "rejected");
convertOrderStatusToStringMap.put(OrderStatus.RETURNED, "returned");
}
// ==================
// = Attributes =
// ==================
private Integer orderId; //Primary key
private OrderStatus status;
private Integer reimbursement;
private String firstName;
private String secondName;
private String passportData;
private String pickUpDate;
private String dropOffDate;
//java.util.Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2011-05-18 16:29:31");
private String customerCell;
private String customerAddress;
// ==================
// = Foreign Keys =
// ==================
private User user;
private Car car;
// ==================
// = Public methods =
// ==================
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getStatus() {
return convertOrderStatusToString(status);
}
public void setStatus(OrderStatus status) {
this.status = status;
}
public Integer getReimbursement() {
return this.reimbursement;
}
public void setReimbursement(Integer value) {
this.reimbursement = value;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public String getPassportData() {
return passportData;
}
public void setPassportData(String passportData) {
this.passportData = passportData;
}
public String getPickUpDate() {
return pickUpDate;
}
public void setPickUpDate(String pickUpDate) {
this.pickUpDate = pickUpDate;
}
public String getDropOffDate() {
return dropOffDate;
}
public void setDropOffDate(String dropOffDate) {
this.dropOffDate = dropOffDate;
}
public String getCustomerCell() {
return customerCell;
}
public void setCustomerCell(String customerCell) {
this.customerCell = customerCell;
}
public String getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public static OrderStatus converStringToOrderStatus(String status) {
return convertStringToOrderStatusMap.get(status);
}
public static String convertOrderStatusToString(OrderStatus status) {
return convertOrderStatusToStringMap.get(status);
}
}
Because a Plain Old Java Object only has data. Adding logic and methods means that it's no longer Plain Old Java Object.
That doesn't necessarily make it a bad thing, but you might be able to refactor the logic out into a class of it's own.
Lets ignore POJO.
What they mean is Service Oriented vs Domain Driven.
Service Oriented follows strict separation of behavior from state. They call POJOs data objects which are essentially glorified structs. Thus you would put the static methods in the Service. In fact you probably wouldn't even want the methods static as that is also against the service oriented approach (see dependency injection and evil singleton).
Domain Driven follows the idea of classic OOP (e.g. Rails Active Record) in which they do believe its OK to put behavior in their POJOs. Consequently because state + behavior are coupled there is only one implementation and thus static methods in the domain object are OK.
If your going the DAO route your most likely doing Service Oriented. My opinion is if your going to do the DAO POJO route you should use immutable objects (shameless plug) for those data objects.
Finally putting an inline enum into a class from my knowledge does not violate any definition of POJO. That being said you should know about #Enumerated since your using JPA.