This commit is contained in:
haerong22
2022-08-14 18:47:15 +09:00
370 changed files with 27043 additions and 1 deletions

235
board/.gitignore vendored Normal file
View File

@@ -0,0 +1,235 @@
# Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij+all,windows,macos,visualstudiocode
# Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij+all,windows,macos,visualstudiocode
### Querydsl
/src/main/generated
### JPA Buddy
.jpb/
### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
.idea/*
#!.idea/codeStyles
#!.idea/runConfigurations
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# Support for Project snippet scope
.vscode/*.code-snippets
# Ignore code-workspaces
*.code-workspace
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### Gradle ###
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
### Gradle Patch ###
# Java heap dump
*.hprof
# End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij+all,windows,macos,visualstudiocode

28
board/HELP.md Normal file
View File

@@ -0,0 +1,28 @@
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Gradle documentation](https://docs.gradle.org)
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.7.2/gradle-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.7.2/gradle-plugin/reference/html/#build-image)
* [Spring Web](https://docs.spring.io/spring-boot/docs/2.7.2/reference/htmlsingle/#web)
* [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.7.2/reference/htmlsingle/#using.devtools)
* [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/2.7.2/reference/htmlsingle/#actuator)
### Guides
The following guides illustrate how to use some features concretely:
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
* [Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/)
### Additional Links
These additional references should also help you:
* [Gradle Build Scans insights for your project's build](https://scans.gradle.com#gradle)

70
board/build.gradle Normal file
View File

@@ -0,0 +1,70 @@
plugins {
id 'org.springframework.boot' version '2.7.0'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.data:spring-data-rest-hal-explorer'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// queryDSL 설정
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
}
tasks.named('test') {
useJUnitPlatform()
}
// Querydsl 설정부
def generated = 'src/main/generated'
// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)
}

4
board/docs/board-erd.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

BIN
board/gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
board/gradlew vendored Normal file
View File

@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
board/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
board/settings.gradle Normal file
View File

@@ -0,0 +1 @@
rootProject.name = 'board'

View File

@@ -0,0 +1,15 @@
package com.example.board;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@ConfigurationPropertiesScan
@SpringBootApplication
public class BoardApplication {
public static void main(String[] args) {
SpringApplication.run(BoardApplication.class, args);
}
}

View File

@@ -0,0 +1,18 @@
package com.example.board.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import java.util.Optional;
@EnableJpaAuditing
@Configuration
public class JpaConfig {
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.of("bobby"); // TODO: 인증기능 구현 시 수정
}
}

View File

@@ -0,0 +1,20 @@
package com.example.board.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
.formLogin()
;
return http.build();
}
}

View File

@@ -0,0 +1,36 @@
package com.example.board.config;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
@Configuration
public class ThymeleafConfig {
@Bean
public SpringResourceTemplateResolver thymeleafTemplateResolver(
SpringResourceTemplateResolver defaultTemplateResolver,
Thymeleaf3Properties thymeleaf3Properties
) {
defaultTemplateResolver.setUseDecoupledLogic(thymeleaf3Properties.isDecoupledLogic());
return defaultTemplateResolver;
}
@RequiredArgsConstructor
@Getter
@ConstructorBinding
@ConfigurationProperties("spring.thymeleaf3")
public static class Thymeleaf3Properties {
/**
* Use Thymeleaf 3 Decoupled Logic
*/
private final boolean decoupledLogic;
}
}

View File

@@ -0,0 +1,43 @@
package com.example.board.controller;
import com.example.board.domain.type.SearchType;
import com.example.board.dto.response.ArticleResponse;
import com.example.board.dto.response.ArticleWithCommentsResponse;
import com.example.board.service.ArticleService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequiredArgsConstructor
@RequestMapping("/articles")
@Controller
public class ArticleController {
private final ArticleService articleService;
@GetMapping
public String articles(
@RequestParam(required = false) SearchType searchType,
@RequestParam(required = false) String searchValue,
@PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable,
ModelMap map) {
map.addAttribute("articles", articleService.searchArticles(searchType, searchValue, pageable).map(ArticleResponse::from));
return "articles/index";
}
@GetMapping("/{articleId}")
public String article(@PathVariable Long articleId, ModelMap map) {
ArticleWithCommentsResponse article = ArticleWithCommentsResponse.from(articleService.getArticle(articleId));
map.addAttribute("article", article);
map.addAttribute("articleComments", article.articleCommentsResponse());
return "articles/detail";
}
}

View File

@@ -0,0 +1,13 @@
package com.example.board.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/")
public String root() {
return "forward:/articles";
}
}

View File

@@ -0,0 +1,71 @@
package com.example.board.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
@Getter
@ToString(callSuper = true)
@Table(indexes = {
@Index(columnList = "title"),
@Index(columnList = "hashtag"),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class Article extends AuditingFields {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
@ManyToOne(optional = false)
private UserAccount userAccount;
@Setter
@Column(nullable = false)
private String title; // 제목
@Setter
@Column(nullable = false, length = 10000)
private String content; // 본문
@Setter
private String hashtag; // 해시태그
@OrderBy("createdAt DESC")
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
@ToString.Exclude
private final Set<ArticleComment> articleComments = new LinkedHashSet<>();
protected Article() {}
private Article(UserAccount userAccount, String title, String content, String hashtag) {
this.userAccount = userAccount;
this.title = title;
this.content = content;
this.hashtag = hashtag;
}
public static Article of(UserAccount userAccount, String title, String content, String hashtag) {
return new Article(userAccount, title, content, hashtag);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Article article)) return false;
return id != null && id.equals(article.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@@ -0,0 +1,59 @@
package com.example.board.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
import java.util.Objects;
@Getter
@ToString(callSuper = true)
@Table(indexes = {
@Index(columnList = "content"),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class ArticleComment extends AuditingFields {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
@ManyToOne(optional = false)
private UserAccount userAccount;
@Setter
@ManyToOne(optional = false)
private Article article; // 게시글 (ID)
@Setter
@Column(nullable = false, length = 500)
private String content; // 본문
protected ArticleComment() {}
private ArticleComment(Article article, UserAccount userAccount, String content) {
this.article = article;
this.userAccount = userAccount;
this.content = content;
}
public static ArticleComment of(Article article, UserAccount userAccount, String content) {
return new ArticleComment(article, userAccount, content);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ArticleComment that)) return false;
return id != null && id.equals(that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@@ -0,0 +1,40 @@
package com.example.board.domain;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Getter
@ToString
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성일시
@CreatedBy
@Column(nullable = false, updatable = false, length = 100)
private String createdBy; // 생성자
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime modifiedAt; // 수정일시
@LastModifiedBy
@Column(nullable = false, length = 100)
private String modifiedBy; //수정자
}

View File

@@ -0,0 +1,67 @@
package com.example.board.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
import java.util.Objects;
@Getter
@ToString
@Table(indexes = {
@Index(columnList = "userId"),
@Index(columnList = "email", unique = true),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class UserAccount extends AuditingFields {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
@Column(nullable = false, length = 50)
private String userId;
@Setter
@Column(nullable = false)
private String userPassword;
@Setter
@Column(length = 100)
private String email;
@Setter
@Column(length = 100)
private String nickname;
@Setter
private String memo;
protected UserAccount() {}
private UserAccount(String userId, String userPassword, String email, String nickname, String memo) {
this.userId = userId;
this.userPassword = userPassword;
this.email = email;
this.nickname = nickname;
this.memo = memo;
}
public static UserAccount of(String userId, String userPassword, String email, String nickname, String memo) {
return new UserAccount(userId, userPassword, email, nickname, memo);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UserAccount userAccount)) return false;
return id != null && id.equals(userAccount.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@@ -0,0 +1,5 @@
package com.example.board.domain.type;
public enum SearchType {
TITLE, CONTENT, ID, NICKNAME, HASHTAG
}

View File

@@ -0,0 +1,43 @@
package com.example.board.dto;
import com.example.board.domain.Article;
import com.example.board.domain.ArticleComment;
import java.time.LocalDateTime;
public record ArticleCommentDto(
Long id,
Long articleId,
UserAccountDto userAccountDto,
String content,
LocalDateTime createdAt,
String createdBy,
LocalDateTime modifiedAt,
String modifiedBy
) {
public static ArticleCommentDto of(Long id, Long articleId, UserAccountDto userAccountDto, String content, LocalDateTime createdAt, String createdBy, LocalDateTime modifiedAt, String modifiedBy) {
return new ArticleCommentDto(id, articleId, userAccountDto, content, createdAt, createdBy, modifiedAt, modifiedBy);
}
public static ArticleCommentDto from(ArticleComment entity) {
return new ArticleCommentDto(
entity.getId(),
entity.getArticle().getId(),
UserAccountDto.from(entity.getUserAccount()),
entity.getContent(),
entity.getCreatedAt(),
entity.getCreatedBy(),
entity.getModifiedAt(),
entity.getModifiedBy()
);
}
public ArticleComment toEntity(Article entity) {
return ArticleComment.of(
entity,
userAccountDto.toEntity(),
content
);
}
}

View File

@@ -0,0 +1,45 @@
package com.example.board.dto;
import com.example.board.domain.Article;
import java.time.LocalDateTime;
public record ArticleDto(
Long id,
UserAccountDto userAccountDto,
String title,
String content,
String hashtag,
LocalDateTime createdAt,
String createdBy,
LocalDateTime modifiedAt,
String modifiedBy
) {
public static ArticleDto of(Long id, UserAccountDto userAccountDto, String title, String content, String hashtag, LocalDateTime createdAt, String createdBy, LocalDateTime modifiedAt, String modifiedBy) {
return new ArticleDto(id, userAccountDto, title, content, hashtag, createdAt, createdBy, modifiedAt, modifiedBy);
}
public static ArticleDto from(Article entity) {
return new ArticleDto(
entity.getId(),
UserAccountDto.from(entity.getUserAccount()),
entity.getTitle(),
entity.getContent(),
entity.getHashtag(),
entity.getCreatedAt(),
entity.getCreatedBy(),
entity.getModifiedAt(),
entity.getModifiedBy()
);
}
public Article toEntity() {
return Article.of(
userAccountDto.toEntity(),
title,
content,
hashtag
);
}
}

View File

@@ -0,0 +1,43 @@
package com.example.board.dto;
import com.example.board.domain.Article;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
public record ArticleWithCommentsDto(
Long id,
UserAccountDto userAccountDto,
Set<ArticleCommentDto> articleCommentDtos,
String title,
String content,
String hashtag,
LocalDateTime createdAt,
String createdBy,
LocalDateTime modifiedAt,
String modifiedBy
) {
public static ArticleWithCommentsDto of(Long id, UserAccountDto userAccountDto, Set<ArticleCommentDto> articleCommentDtos, String title, String content, String hashtag, LocalDateTime createdAt, String createdBy, LocalDateTime modifiedAt, String modifiedBy) {
return new ArticleWithCommentsDto(id, userAccountDto, articleCommentDtos, title, content, hashtag, createdAt, createdBy, modifiedAt, modifiedBy);
}
public static ArticleWithCommentsDto from(Article entity) {
return new ArticleWithCommentsDto(
entity.getId(),
UserAccountDto.from(entity.getUserAccount()),
entity.getArticleComments().stream()
.map(ArticleCommentDto::from)
.collect(Collectors.toCollection(LinkedHashSet::new)),
entity.getTitle(),
entity.getContent(),
entity.getHashtag(),
entity.getCreatedAt(),
entity.getCreatedBy(),
entity.getModifiedAt(),
entity.getModifiedBy()
);
}
}

View File

@@ -0,0 +1,48 @@
package com.example.board.dto;
import com.example.board.domain.UserAccount;
import java.time.LocalDateTime;
public record UserAccountDto(
Long id,
String userId,
String userPassword,
String email,
String nickname,
String memo,
LocalDateTime createdAt,
String createdBy,
LocalDateTime modifiedAt,
String modifiedBy
) {
public static UserAccountDto of(Long id, String userId, String userPassword, String email, String nickname, String memo, LocalDateTime createdAt, String createdBy, LocalDateTime modifiedAt, String modifiedBy) {
return new UserAccountDto(id, userId, userPassword, email, nickname, memo, createdAt, createdBy, modifiedAt, modifiedBy);
}
public static UserAccountDto from(UserAccount entity) {
return new UserAccountDto(
entity.getId(),
entity.getUserId(),
entity.getUserPassword(),
entity.getEmail(),
entity.getNickname(),
entity.getMemo(),
entity.getCreatedAt(),
entity.getCreatedBy(),
entity.getModifiedAt(),
entity.getModifiedBy()
);
}
public UserAccount toEntity() {
return UserAccount.of(
userId,
userPassword,
email,
nickname,
memo
);
}
}

View File

@@ -0,0 +1,35 @@
package com.example.board.dto.response;
import com.example.board.dto.ArticleCommentDto;
import java.io.Serializable;
import java.time.LocalDateTime;
public record ArticleCommentResponse(
Long id,
String content,
LocalDateTime createdAt,
String email,
String nickname
) implements Serializable {
public static ArticleCommentResponse of(Long id, String content, LocalDateTime createdAt, String email, String nickname) {
return new ArticleCommentResponse(id, content, createdAt, email, nickname);
}
public static ArticleCommentResponse from(ArticleCommentDto dto) {
String nickname = dto.userAccountDto().nickname();
if (nickname == null || nickname.isBlank()) {
nickname = dto.userAccountDto().userId();
}
return new ArticleCommentResponse(
dto.id(),
dto.content(),
dto.createdAt(),
dto.userAccountDto().email(),
nickname
);
}
}

View File

@@ -0,0 +1,39 @@
package com.example.board.dto.response;
import com.example.board.dto.ArticleDto;
import java.io.Serializable;
import java.time.LocalDateTime;
public record ArticleResponse(
Long id,
String title,
String content,
String hashtag,
LocalDateTime createdAt,
String email,
String nickname
) implements Serializable {
public static ArticleResponse of(Long id, String title, String content, String hashtag, LocalDateTime createdAt, String email, String nickname) {
return new ArticleResponse(id, title, content, hashtag, createdAt, email, nickname);
}
public static ArticleResponse from(ArticleDto dto) {
String nickname = dto.userAccountDto().nickname();
if (nickname == null || nickname.isBlank()) {
nickname = dto.userAccountDto().userId();
}
return new ArticleResponse(
dto.id(),
dto.title(),
dto.content(),
dto.hashtag(),
dto.createdAt(),
dto.userAccountDto().email(),
nickname
);
}
}

View File

@@ -0,0 +1,46 @@
package com.example.board.dto.response;
import com.example.board.dto.ArticleWithCommentsDto;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
public record ArticleWithCommentsResponse(
Long id,
String title,
String content,
String hashtag,
LocalDateTime createdAt,
String email,
String nickname,
Set<ArticleCommentResponse> articleCommentsResponse
) implements Serializable {
public static ArticleWithCommentsResponse of(Long id, String title, String content, String hashtag, LocalDateTime createdAt, String email, String nickname, Set<ArticleCommentResponse> articleCommentResponses) {
return new ArticleWithCommentsResponse(id, title, content, hashtag, createdAt, email, nickname, articleCommentResponses);
}
public static ArticleWithCommentsResponse from(ArticleWithCommentsDto dto) {
String nickname = dto.userAccountDto().nickname();
if (nickname == null || nickname.isBlank()) {
nickname = dto.userAccountDto().userId();
}
return new ArticleWithCommentsResponse(
dto.id(),
dto.title(),
dto.content(),
dto.hashtag(),
dto.createdAt(),
dto.userAccountDto().email(),
nickname,
dto.articleCommentDtos().stream()
.map(ArticleCommentResponse::from)
.collect(Collectors.toCollection(LinkedHashSet::new))
);
}
}

View File

@@ -0,0 +1,32 @@
package com.example.board.repository;
import com.example.board.domain.ArticleComment;
import com.example.board.domain.QArticleComment;
import com.querydsl.core.types.dsl.DateTimeExpression;
import com.querydsl.core.types.dsl.StringExpression;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.List;
@RepositoryRestResource
public interface ArticleCommentRepository extends
JpaRepository<ArticleComment, Long>,
QuerydslPredicateExecutor<ArticleComment>,
QuerydslBinderCustomizer<QArticleComment>
{
List<ArticleComment> findByArticle_Id(Long articleId);
@Override
default void customize(QuerydslBindings bindings, QArticleComment root) {
bindings.excludeUnlistedProperties(true);
bindings.including(root.content, root.createdAt, root.createdBy);
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdAt).first(DateTimeExpression::eq);
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
}
}

View File

@@ -0,0 +1,39 @@
package com.example.board.repository;
import com.example.board.domain.Article;
import com.example.board.domain.QArticle;
import com.querydsl.core.types.dsl.DateTimeExpression;
import com.querydsl.core.types.dsl.StringExpression;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource
public interface ArticleRepository extends
JpaRepository<Article, Long>,
QuerydslPredicateExecutor<Article>,
QuerydslBinderCustomizer<QArticle>
{
Page<Article> findByTitleContaining(String title, Pageable pageable);
Page<Article> findByContentContaining(String content, Pageable pageable);
Page<Article> findByUserAccount_UserIdContaining(String userId, Pageable pageable);
Page<Article> findByUserAccount_NicknameContaining(String nickname, Pageable pageable);
Page<Article> findByHashtag(String hashtag, Pageable pageable);
@Override
default void customize(QuerydslBindings bindings, QArticle root) {
bindings.excludeUnlistedProperties(true);
bindings.including(root.title, root.content, root.hashtag, root.createdAt, root.createdBy);
// bindings.bind(root.title).first(StringExpression::likeIgnoreCase); // like '${v}'
bindings.bind(root.title).first(StringExpression::containsIgnoreCase); // like '%${v}%'
bindings.bind(root.content ).first(StringExpression::containsIgnoreCase);
bindings.bind(root.hashtag).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdAt).first(DateTimeExpression::eq);
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
}
}

View File

@@ -0,0 +1,7 @@
package com.example.board.repository;
import com.example.board.domain.UserAccount;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserAccountRepository extends JpaRepository<UserAccount, Long> {
}

View File

@@ -0,0 +1,31 @@
package com.example.board.service;
import com.example.board.dto.ArticleCommentDto;
import com.example.board.repository.ArticleCommentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Transactional
@Service
public class ArticleCommentService {
private final ArticleCommentRepository articleCommentRepository;
@Transactional(readOnly = true)
public List<ArticleCommentDto> searchArticleComments(Long articleId) {
return List.of();
}
public void saveArticleComment(ArticleCommentDto dto) {
}
public void updateArticleComment(ArticleCommentDto dto) {
}
public void deleteArticleComment(Long articleCommentId) {
}
}

View File

@@ -0,0 +1,72 @@
package com.example.board.service;
import com.example.board.domain.Article;
import com.example.board.domain.type.SearchType;
import com.example.board.dto.ArticleDto;
import com.example.board.dto.ArticleWithCommentsDto;
import com.example.board.repository.ArticleRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityNotFoundException;
@Slf4j
@RequiredArgsConstructor
@Transactional
@Service
public class ArticleService {
private final ArticleRepository articleRepository;
@Transactional(readOnly = true)
public Page<ArticleDto> searchArticles(SearchType searchType, String searchKeyword, Pageable pageable) {
if (searchKeyword == null || searchKeyword.isBlank()) {
return articleRepository.findAll(pageable).map(ArticleDto::from);
}
return switch (searchType) {
case TITLE -> articleRepository.findByTitleContaining(searchKeyword, pageable).map(ArticleDto::from);
case CONTENT -> articleRepository.findByContentContaining(searchKeyword, pageable).map(ArticleDto::from);
case ID -> articleRepository.findByUserAccount_UserIdContaining(searchKeyword, pageable).map(ArticleDto::from);
case NICKNAME -> articleRepository.findByUserAccount_NicknameContaining(searchKeyword, pageable).map(ArticleDto::from);
case HASHTAG -> articleRepository.findByHashtag("#" + searchKeyword, pageable).map(ArticleDto::from);
};
}
@Transactional(readOnly = true)
public ArticleWithCommentsDto getArticle(Long articleId) {
return articleRepository.findById(articleId)
.map(ArticleWithCommentsDto::from)
.orElseThrow(() -> new EntityNotFoundException("게시글이 없습니다 - articleId: " + articleId));
}
public void saveArticle(ArticleDto dto) {
articleRepository.save(dto.toEntity());
}
public void updateArticle(ArticleDto dto) {
try {
Article article = articleRepository.getReferenceById(dto.id());
if (dto.title() != null) {
article.setTitle(dto.title());
}
if (dto.content() != null) {
article.setContent(dto.content());
}
article.setHashtag(dto.hashtag());
} catch (EntityNotFoundException e) {
log.warn("게시글 업데이트 실패. 게시글을 찾을 수 없습니다 - dto: {}", dto);
}
}
public void deleteArticle(long articleId) {
articleRepository.deleteById(articleId);
}
}

View File

@@ -0,0 +1,43 @@
debug: false
management.endpoints.web.exposure.include: "*"
logging:
level:
com.example.board: debug
org.springframework.web.servlet: debug
org.hibernate.type.descriptor.sql.BasicBinder: trace
spring:
datasource:
url: jdbc:mysql://localhost:3306/board
username: bobby
password: localhostTEST
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
open-in-view: false
defer-datasource-initialization: true
hibernate:
ddl-auto: create
# open-in-view: false
show-sql: true
properties:
hibernate.format_sql: true
hibernate.default_batch_fetch_size: 100
# h2.console.enabled: true
sql.init.mode: always
data:
rest:
base-path: /api
detection-strategy: annotated
thymeleaf3:
decoupled-logic: true
---
spring:
config.activate.on-profile: testdb
# datasource:
# url: jdbc:h2:mem:board;mode=mysql
# driver-class-name: org.h2.Driver
# sql.init.mode: always
# test.database.replace: none

View File

@@ -0,0 +1,684 @@
-- 테스트 계정
-- TODO: 테스트용이지만 비밀번호가 노출된 데이터 세팅. 개선하는 것이 좋을 지 고민해 보자.
insert into user_account (user_id, user_password, nickname, email, memo, created_at, created_by, modified_at, modified_by) values
('bobby', '1234', 'bobby', 'bobby@mail.com', 'I am Bobby.', now(), 'bobby', now(), 'bobby')
;
-- 123 게시글
insert into article (user_account_id, title, content, hashtag, created_by, modified_by, created_at, modified_at) values
(1, 'Quisque ut erat.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.
Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.
Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '#pink', 'Kamilah', 'Murial', '2021-05-30 23:53:46', '2021-03-10 08:48:50'),
(1, 'Morbi ut odio.', 'Phasellus in felis. Donec semper sapien a libero. Nam dui.
Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.
Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '#purple', 'Arv', 'Keelby', '2021-05-06 11:51:24', '2021-05-23 08:34:54'),
(1, 'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio.', 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '#purple', 'Adams', 'Thalia', '2021-08-13 08:32:22', '2021-04-02 02:58:19'),
(1, 'Fusce posuere felis sed lacus.', 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '#mauv', 'Johny', 'Constantin', '2021-09-05 04:28:16', '2021-10-31 17:46:08'),
(1, 'Aliquam erat volutpat.', 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '#green', 'Karlene', 'Marmaduke', '2022-01-25 16:10:23', '2021-11-08 08:47:03'),
(1, 'Donec ut mauris eget massa tempor convallis.', 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#maroon', 'Alonso', 'Eustacia', '2022-01-26 06:33:42', '2021-12-08 11:27:30'),
(1, 'Nullam molestie nibh in lectus.', 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.
Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '#orange', 'Dedra', 'Wilek', '2021-05-04 19:51:29', '2021-10-09 16:52:09'),
(1, 'Sed ante.', 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.
Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '#teal', 'Doe', 'Jodi', '2021-10-23 23:45:21', '2021-08-05 14:19:36'),
(1, 'In hac habitasse platea dictumst.', 'Sed ante. Vivamus tortor. Duis mattis egestas metus.
Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '#khaki', 'Fitz', 'Jemmie', '2021-01-10 21:03:03', '2021-04-15 05:02:39'),
(1, 'Vivamus in felis eu sapien cursus vestibulum.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#puce', 'Grace', 'Bryn', '2021-09-28 07:01:29', '2021-09-01 13:54:55'),
(1, 'Morbi a ipsum.', 'Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '#orange', 'Lalo', 'Lorrie', '2022-01-26 03:40:15', '2021-07-18 05:30:34'),
(1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', 'Sed ante. Vivamus tortor. Duis mattis egestas metus.
Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '#purple', 'Jane', 'Tresa', '2021-07-22 22:25:07', '2021-05-16 14:20:27'),
(1, 'Duis at velit eu est congue elementum.', 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '#maroon', 'Cookie', 'Rosalia', '2021-02-20 10:06:13', '2021-10-10 06:05:30'),
(1, 'In hac habitasse platea dictumst.', 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', null, 'Gerti', 'Everard', '2021-08-17 15:14:51', '2021-10-01 13:01:41'),
(1, 'Nulla suscipit ligula in lacus.', 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.
Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '#khaki', 'Adolf', 'Tiff', '2021-12-03 03:44:00', '2021-07-12 00:20:12'),
(1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.
Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.', null, 'Vivyanne', 'Humbert', '2021-08-11 04:04:05', '2021-09-05 17:15:51'),
(1, 'Donec semper sapien a libero.', 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', null, 'Ki', 'Ophelia', '2021-12-21 13:27:54', '2021-05-07 08:06:52'),
(1, 'Quisque id justo sit amet sapien dignissim vestibulum.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '#goldenrod', 'Jackelyn', 'Vlad', '2021-06-29 13:00:35', '2021-05-11 00:47:43'),
(1, 'Morbi quis tortor id nulla ultrices aliquet.', 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '#yellow', 'Jesus', 'Peri', '2021-06-18 20:56:37', '2021-07-05 18:44:15'),
(1, 'In sagittis dui vel nisl.', 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.
Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '#orange', 'Abbot', 'Carolann', '2021-06-16 12:20:50', '2021-01-26 02:34:46'),
(1, 'Integer non velit.', 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.
Phasellus in felis. Donec semper sapien a libero. Nam dui.', '#fuscia', 'Shae', 'Rhody', '2021-01-14 23:22:59', '2022-01-31 12:02:00'),
(1, 'Quisque id justo sit amet sapien dignissim vestibulum.', 'Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.
Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '#puce', 'Dominik', 'Enos', '2021-12-17 17:42:09', '2021-06-28 19:55:49'),
(1, 'Nullam varius.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.
Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', null, 'Sheila-kathryn', 'Lil', '2021-06-11 13:47:12', '2021-11-30 13:45:21'),
(1, 'Sed ante.', 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.
Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.
Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '#teal', 'Moina', 'Coletta', '2021-09-01 00:39:21', '2021-06-20 13:09:41'),
(1, 'Morbi non lectus.', 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.
In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.
Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '#fuscia', 'Niel', 'Alexio', '2021-04-13 02:59:34', '2021-01-26 00:43:20'),
(1, 'Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla.', 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '#maroon', 'Gannie', 'Alicea', '2021-05-18 21:27:32', '2021-04-26 23:42:00'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.
In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.
Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '#teal', 'Burg', 'Saudra', '2022-01-09 16:49:14', '2021-01-30 05:24:22'),
(1, 'Nulla justo.', 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.
Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.
Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '#turquoise', 'Monah', 'Alexandro', '2021-08-25 08:42:32', '2021-06-24 17:50:44'),
(1, 'Pellentesque viverra pede ac diam.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '#fuscia', 'Tadeas', 'Lynnelle', '2021-04-16 16:05:00', '2021-11-18 17:42:45'),
(1, 'Curabitur gravida nisi at nibh.', 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', null, 'Clim', 'Carin', '2021-11-14 22:48:52', '2021-01-15 04:11:23'),
(1, 'Duis aliquam convallis nunc.', 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.
Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '#blue', 'Vonnie', 'Amery', '2021-07-07 06:30:56', '2021-06-21 07:33:19'),
(1, 'Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.
Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '#yellow', 'Billi', 'Laure', '2021-10-22 11:07:01', '2022-01-24 21:15:02'),
(1, 'Donec semper sapien a libero.', 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '#pink', 'Terese', 'Dalli', '2021-07-04 02:06:12', '2021-10-27 03:27:56'),
(1, 'Phasellus in felis.', 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.
Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '#goldenrod', 'Arlen', 'Francoise', '2021-03-06 10:32:19', '2021-09-16 12:49:52'),
(1, 'Etiam vel augue.', 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.
Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '#blue', 'Roderich', 'Daphna', '2021-07-29 05:37:58', '2021-09-09 14:57:16'),
(1, 'In hac habitasse platea dictumst.', 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.
Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.', null, 'Jeremy', 'Allx', '2021-03-29 02:31:37', '2021-10-04 04:51:02'),
(1, 'Nunc purus.', 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '#purple', 'Neely', 'Hubey', '2021-12-09 23:08:51', '2022-01-19 22:52:00'),
(1, 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa.', 'Fusce consequat. Nulla nisl. Nunc nisl.
Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.', '#green', 'Kasper', 'Nealy', '2021-01-06 11:57:12', '2021-09-22 23:51:12'),
(1, 'Curabitur at ipsum ac tellus semper interdum.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', null, 'Herminia', 'Alexandra', '2022-01-24 16:01:31', '2021-09-04 09:45:28'),
(1, 'Morbi non lectus.', 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.
Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '#turquoise', 'Dionne', 'Arvy', '2021-04-07 19:45:14', '2021-05-04 04:31:17'),
(1, 'Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante.', 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', null, 'Armin', 'Hetti', '2021-12-13 04:47:57', '2021-11-21 10:40:03'),
(1, 'Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla.', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '#fuscia', 'Eamon', 'Alberta', '2021-01-14 18:42:07', '2021-08-08 01:49:02'),
(1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante.', 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.
Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.
Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.', '#violet', 'Udale', 'Steffane', '2021-01-09 05:17:28', '2022-01-07 13:29:29'),
(1, 'Ut tellus.', 'Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.
Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.
Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', null, 'Jackie', 'Emelda', '2021-11-20 09:06:53', '2021-06-29 21:11:43'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '#red', 'Judye', 'Hulda', '2022-01-31 02:12:17', '2021-11-13 04:25:33'),
(1, 'Donec quis orci eget orci vehicula condimentum.', 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.
In congue. Etiam justo. Etiam pretium iaculis justo.', null, 'Hana', 'Anabel', '2021-05-19 15:38:50', '2021-09-18 12:45:53'),
(1, 'Pellentesque eget nunc.', 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '#purple', 'Gil', 'Gerri', '2021-07-13 02:04:06', '2021-04-28 03:43:55'),
(1, 'Nam dui.', 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '#crimson', 'Peyton', 'Leena', '2021-01-09 14:46:57', '2021-10-20 07:05:55'),
(1, 'Morbi a ipsum.', 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.
Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.', '#indigo', 'Pepillo', 'Bride', '2021-07-23 15:14:41', '2021-07-29 20:10:02'),
(1, 'Aenean auctor gravida sem.', 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '#khaki', 'Tull', 'Tracee', '2021-03-01 23:36:57', '2021-04-20 05:54:22'),
(1, 'Morbi quis tortor id nulla ultrices aliquet.', 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', null, 'Gregorius', 'Marlane', '2021-08-16 16:20:12', '2021-09-28 15:21:22'),
(1, 'Nulla nisl.', 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '#turquoise', 'Cindi', 'Cary', '2021-09-29 02:56:11', '2021-04-26 00:16:31'),
(1, 'Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc.', 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.
Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', null, 'Rachel', 'Maurise', '2021-11-05 23:17:06', '2021-06-02 11:12:17'),
(1, 'Morbi non quam nec dui luctus rutrum.', 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '#pink', 'Muriel', 'Ki', '2021-06-29 18:05:20', '2021-11-14 19:30:51'),
(1, 'Phasellus in felis.', 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.
Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.
Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '#orange', 'Emanuele', 'Frank', '2021-01-13 10:45:47', '2022-01-07 02:08:42'),
(1, 'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi.', 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.
Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', null, 'Arlen', 'Kelley', '2021-01-18 04:14:36', '2021-01-12 15:49:40'),
(1, 'Nunc nisl.', 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '#orange', 'Brant', 'Rycca', '2021-10-24 18:34:37', '2021-09-24 11:55:07'),
(1, 'Nulla justo.', 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '#pink', 'Glenn', 'Isaiah', '2021-12-27 21:37:13', '2021-06-21 11:23:36'),
(1, 'Praesent lectus.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#crimson', 'Doro', 'Adah', '2021-04-15 20:39:03', '2021-07-29 20:08:20'),
(1, 'Etiam pretium iaculis justo.', 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.
Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '#crimson', 'Coletta', 'Magdalene', '2021-11-14 13:15:09', '2021-10-13 16:51:20'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.
Sed ante. Vivamus tortor. Duis mattis egestas metus.', '#teal', 'Miltie', 'Krissy', '2021-11-29 14:30:18', '2021-06-28 06:23:31'),
(1, 'Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue.', 'Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.
Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.
Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', null, 'Alvan', 'Stu', '2021-02-07 15:13:30', '2021-03-20 08:42:35'),
(1, 'Maecenas tincidunt lacus at velit.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '#violet', 'Lurleen', 'Sly', '2021-10-12 02:16:28', '2021-03-28 22:35:10'),
(1, 'Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '#violet', 'Gus', 'Roy', '2021-04-30 18:14:12', '2021-08-07 12:28:47'),
(1, 'Nulla facilisi.', 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.
Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '#violet', 'Alfons', 'Meredith', '2021-11-30 09:26:07', '2021-05-25 03:28:14'),
(1, 'Nunc nisl.', 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.
Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.
Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '#turquoise', 'Alaine', 'Kaile', '2021-05-19 04:01:38', '2022-01-20 20:21:15'),
(1, 'Praesent blandit lacinia erat.', 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.
Sed ante. Vivamus tortor. Duis mattis egestas metus.', '#puce', 'Bancroft', 'Brittne', '2021-11-07 20:25:38', '2021-07-15 23:44:30'),
(1, 'Quisque porta volutpat erat.', 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#fuscia', 'Sibyl', 'Felicia', '2021-07-23 03:14:59', '2021-09-23 12:59:16'),
(1, 'In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', null, 'Nikos', 'Brooks', '2021-05-26 23:29:09', '2021-10-30 22:20:34'),
(1, 'Proin eu mi.', 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.
Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.
Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.', '#puce', 'Christa', 'Avrom', '2021-01-03 15:19:52', '2021-07-26 09:56:42'),
(1, 'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam.', 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#pink', 'Kassey', 'Abbi', '2021-10-23 18:21:35', '2021-08-12 08:13:10'),
(1, 'Fusce posuere felis sed lacus.', 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '#fuscia', 'Thebault', 'Adi', '2021-04-23 16:56:09', '2022-01-14 06:35:51'),
(1, 'Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.
Phasellus in felis. Donec semper sapien a libero. Nam dui.', '#red', 'Claire', 'Alyson', '2021-06-05 04:03:52', '2021-04-21 16:51:40'),
(1, 'Proin eu mi.', 'Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.
Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', null, 'Rodrick', 'Judd', '2021-09-15 04:12:40', '2021-07-16 08:11:59'),
(1, 'Cras in purus eu magna vulputate luctus.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.
Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '#turquoise', 'Heidi', 'Madlen', '2021-09-28 19:02:55', '2021-07-10 16:49:00'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.
In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '#blue', 'Yasmeen', 'Edie', '2021-12-29 02:35:31', '2021-09-28 00:32:13'),
(1, 'Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante.', 'In congue. Etiam justo. Etiam pretium iaculis justo.
In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.
Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '#pink', 'Abbot', 'Nicoline', '2022-01-30 03:12:36', '2021-06-05 04:08:51'),
(1, 'Nulla suscipit ligula in lacus.', 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.
Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.
Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', null, 'Guthry', 'Darla', '2021-05-17 21:21:38', '2021-12-25 10:06:03'),
(1, 'Maecenas rhoncus aliquam lacus.', 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', null, 'Andris', 'Leigh', '2021-02-16 03:49:50', '2021-01-23 08:55:39'),
(1, 'Vestibulum ac est lacinia nisi venenatis tristique.', 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.
In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '#purple', 'Alika', 'Egbert', '2021-03-25 21:56:32', '2021-08-06 09:25:55'),
(1, 'In congue.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '#violet', 'Rosaleen', 'Laurel', '2021-05-31 02:31:10', '2021-05-25 07:40:17'),
(1, 'Nam tristique tortor eu pede.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.
Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '#turquoise', 'Rosie', 'Jeddy', '2021-04-21 13:04:12', '2021-12-21 21:27:10'),
(1, 'In sagittis dui vel nisl.', 'Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.
Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '#purple', 'Hermann', 'Dynah', '2021-08-11 15:17:07', '2021-07-26 14:59:15'),
(1, 'Ut tellus.', 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.
Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.
Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.', '#crimson', 'Blanch', 'Florinda', '2021-04-07 02:11:09', '2021-03-11 07:18:08'),
(1, 'Pellentesque at nulla.', 'Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.
Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '#teal', 'Gleda', 'Ellary', '2021-02-09 04:55:31', '2021-06-03 13:44:00'),
(1, 'Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', 'Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis.
Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.
Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '#red', 'Joete', 'Tedmund', '2021-02-24 21:47:59', '2021-03-26 22:36:33'),
(1, 'Suspendisse potenti.', 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.
In congue. Etiam justo. Etiam pretium iaculis justo.
In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', null, 'Jamie', 'Alexa', '2021-08-06 04:32:39', '2021-02-19 12:04:36'),
(1, 'Nulla suscipit ligula in lacus.', 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.
Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '#violet', 'Doris', 'Mendel', '2021-09-17 11:09:35', '2021-05-08 09:41:26'),
(1, 'Nulla ac enim.', 'Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', null, 'Bartie', 'Tess', '2021-11-23 16:40:31', '2021-02-14 18:25:25'),
(1, 'Morbi ut odio.', 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '#khaki', 'Sile', 'Bertram', '2021-07-05 03:55:44', '2021-04-26 06:11:20'),
(1, 'Proin interdum mauris non ligula pellentesque ultrices.', 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.
Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '#orange', 'Stillman', 'Robinett', '2021-01-28 08:36:31', '2022-01-22 04:26:21'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.
Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.
Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '#purple', 'Teresa', 'Geordie', '2021-10-01 23:56:53', '2021-03-14 14:48:32'),
(1, 'Vivamus in felis eu sapien cursus vestibulum.', 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.
Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', '#turquoise', 'Silvie', 'Ely', '2021-06-25 15:27:52', '2021-07-11 22:35:10'),
(1, 'Sed ante.', 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.
Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.
Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '#turquoise', 'Marline', 'Avigdor', '2021-10-28 11:05:02', '2022-01-01 22:59:45'),
(1, 'Morbi non quam nec dui luctus rutrum.', 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.
Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis.', '#fuscia', 'Bella', 'Redd', '2021-07-25 10:58:10', '2022-01-03 06:44:01'),
(1, 'Donec ut mauris eget massa tempor convallis.', 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '#maroon', 'Rubie', 'Gallard', '2021-04-17 00:00:13', '2021-01-01 16:09:42'),
(1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', 'In congue. Etiam justo. Etiam pretium iaculis justo.
In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.
Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '#yellow', 'Meghan', 'Bone', '2021-10-01 06:58:34', '2021-08-06 07:47:53'),
(1, 'Integer non velit.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '#orange', 'Meris', 'Griffin', '2021-04-19 01:54:16', '2021-04-23 08:04:24'),
(1, 'Donec dapibus.', 'In congue. Etiam justo. Etiam pretium iaculis justo.
In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.
Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '#violet', 'Amy', 'Tann', '2021-05-06 13:30:44', '2021-12-04 03:54:16'),
(1, 'Duis at velit eu est congue elementum.', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.
Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '#crimson', 'Colan', 'Anthe', '2021-11-27 23:07:19', '2021-04-21 19:58:19'),
(1, 'Etiam justo.', 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.
In congue. Etiam justo. Etiam pretium iaculis justo.', null, 'Honor', 'Fayina', '2021-05-14 16:02:48', '2022-01-07 21:17:52'),
(1, 'Pellentesque eget nunc.', 'Sed ante. Vivamus tortor. Duis mattis egestas metus.
Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.
Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '#puce', 'Brooke', 'Demetris', '2021-11-14 19:35:48', '2021-09-27 23:55:31'),
(1, 'Curabitur gravida nisi at nibh.', 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.
In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '#red', 'Regina', 'Son', '2021-09-05 08:18:57', '2021-08-29 18:59:01'),
(1, 'Sed sagittis.', 'Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis.
Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.
Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '#khaki', 'Matelda', 'Alla', '2021-09-08 21:13:52', '2021-07-02 08:49:38'),
(1, 'Morbi porttitor lorem id ligula.', 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '#turquoise', 'Brock', 'Ludwig', '2021-06-26 11:28:38', '2021-07-24 17:24:01'),
(1, 'Fusce consequat.', 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#red', 'Kat', 'Zelig', '2021-09-24 11:37:56', '2021-07-12 13:57:43'),
(1, 'Maecenas ut massa quis augue luctus tincidunt.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#blue', 'Thaddus', 'Merna', '2021-05-23 13:06:03', '2021-03-24 08:32:10'),
(1, 'Pellentesque viverra pede ac diam.', 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.
In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.
Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', null, 'Ronnie', 'Brittaney', '2021-12-26 19:23:32', '2021-09-05 19:27:21'),
(1, 'In quis justo.', 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.
Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.
Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', null, 'Byron', 'Randy', '2021-08-18 13:40:37', '2021-12-28 08:34:19'),
(1, 'Fusce consequat.', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.
Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', null, 'Neron', 'Christa', '2021-05-24 18:32:45', '2021-01-01 16:15:57'),
(1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.
Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.
In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '#yellow', 'Merilee', 'Dolli', '2021-04-20 00:10:42', '2021-03-27 16:42:26'),
(1, 'Proin at turpis a pede posuere nonummy.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.
Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.
Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '#indigo', 'Caron', 'Valle', '2021-11-23 23:38:55', '2021-03-23 16:50:35'),
(1, 'Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '#mauv', 'Delbert', 'Cammy', '2021-06-03 08:38:23', '2021-07-16 21:36:19'),
(1, 'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est.', 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.
Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.
Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '#crimson', 'Konstantin', 'Sarine', '2021-12-21 13:46:23', '2021-12-27 03:46:03'),
(1, 'Nunc purus.', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.
Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', null, 'Krysta', 'Euphemia', '2021-05-03 23:53:27', '2021-04-16 15:39:57'),
(1, 'Etiam pretium iaculis justo.', 'Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis.', '#turquoise', 'Oliver', 'Clint', '2021-06-12 07:00:00', '2021-06-14 11:33:22'),
(1, 'In quis justo.', 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '#red', 'Vito', 'Bird', '2021-06-20 08:39:02', '2021-05-06 03:06:08'),
(1, 'In sagittis dui vel nisl.', 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', null, 'Errick', 'Shirlee', '2021-08-18 08:08:42', '2021-11-04 15:44:08'),
(1, 'Integer ac leo.', 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.
Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.
Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '#puce', 'Benjamin', 'Arlie', '2021-11-23 02:21:46', '2021-02-13 07:35:14'),
(1, 'Morbi non quam nec dui luctus rutrum.', 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.
Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', '#yellow', 'Tessy', 'Nan', '2021-10-07 20:30:36', '2021-03-06 01:51:12'),
(1, 'Nulla justo.', 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', null, 'Babette', 'Dudley', '2021-02-05 15:19:07', '2021-04-01 14:46:59'),
(1, 'Aenean lectus.', 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.
Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '#yellow', 'Hoyt', 'Austina', '2021-06-26 18:20:38', '2021-02-20 16:09:49'),
(1, 'Ut tellus.', 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.
Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', null, 'Wilmer', 'Ingra', '2021-07-19 14:18:17', '2022-01-23 17:29:54')
;
-- 1000 댓글
insert into article_comment (article_id, user_account_id, content, created_at, modified_at, created_by, modified_by) values
(49, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-03-02 22:40:04', '2021-04-27 15:38:09', 'Lind', 'Orv'),
(108, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-06-08 04:36:02', '2022-01-25 15:35:42', 'Trstram', 'Loy'),
(31, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-04-10 00:47:10', '2021-02-06 20:58:04', 'Duff', 'Early'),
(120, 1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '2021-08-21 08:39:39', '2021-11-17 22:47:35', 'Sydney', 'Boony'),
(123, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-06-17 10:57:29', '2021-05-13 12:28:47', 'Burk', 'Markus'),
(39, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2022-01-15 11:37:12', '2021-02-19 17:42:22', 'Calvin', 'Garreth'),
(30, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-11-23 18:29:30', '2021-03-09 00:57:27', 'Kain', 'Bruno'),
(57, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-03-19 18:39:02', '2021-03-16 17:47:17', 'Kippie', 'Alexio'),
(41, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-03-21 16:34:30', '2021-03-17 15:18:55', 'Frannie', 'Horacio'),
(100, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-02-24 16:53:08', '2021-05-09 06:00:58', 'Osborn', 'Pren'),
(48, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2021-03-29 08:26:41', '2021-11-22 20:55:26', 'Dorie', 'Georgie'),
(122, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-06-12 07:38:25', '2021-03-03 07:14:43', 'Obed', 'Chrissy'),
(87, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-05-11 08:47:16', '2021-04-13 00:47:50', 'Reinhard', 'Robbert'),
(100, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2022-01-18 23:33:51', '2022-01-14 12:38:23', 'Clim', 'Chester'),
(22, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-09-18 10:27:37', '2021-09-29 20:31:09', 'Odie', 'Britt'),
(97, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-12-14 01:55:52', '2021-11-02 15:12:00', 'Ulises', 'Denney'),
(103, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-04-03 11:44:04', '2022-01-05 21:01:34', 'Kendricks', 'Aubert'),
(25, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-05-25 09:46:40', '2021-10-10 18:46:59', 'Dal', 'Maxy'),
(91, 1, 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '2021-04-29 23:36:48', '2021-12-03 12:08:48', 'Vaclav', 'Patric'),
(18, 1, 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', '2021-09-26 00:29:13', '2021-07-10 01:44:07', 'Carl', 'Riley'),
(89, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-12-11 05:07:10', '2021-05-31 15:26:03', 'Dex', 'Wallas'),
(107, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-10-31 11:33:44', '2021-03-04 15:19:35', 'Lutero', 'Hussein'),
(90, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-08-17 14:52:58', '2021-11-24 16:28:01', 'Garvy', 'Gris'),
(121, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-02-17 16:50:19', '2021-01-31 09:21:51', 'Shayne', 'Stafford'),
(91, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-06-23 10:06:39', '2021-10-27 22:04:41', 'Haze', 'Giraldo'),
(32, 1, 'Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.', '2021-10-21 19:41:56', '2021-03-12 02:47:38', 'Cobbie', 'Thornton'),
(47, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-05-02 07:45:04', '2021-06-26 13:36:44', 'Humfried', 'Bram'),
(92, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-10-22 04:46:24', '2021-07-06 02:25:34', 'Luis', 'Chicky'),
(76, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-12-30 18:39:24', '2021-10-13 03:58:46', 'Derwin', 'Zacherie'),
(31, 1, 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '2021-11-07 02:25:31', '2021-11-30 11:15:34', 'Boris', 'Egbert'),
(29, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-11-27 19:03:53', '2021-02-16 07:42:30', 'Gabriel', 'Gary'),
(115, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-12-30 17:50:07', '2021-10-13 11:06:50', 'Gilles', 'Derrek'),
(106, 1, 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '2021-06-10 02:26:59', '2021-12-17 18:00:38', 'Jodie', 'Whitney'),
(5, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-04-16 12:44:52', '2022-01-19 17:32:59', 'Palmer', 'Orton'),
(115, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-09-09 05:12:56', '2021-07-31 05:07:35', 'Mahmoud', 'Urson'),
(112, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-01-31 06:52:27', '2021-02-07 17:19:58', 'Dunn', 'Monti'),
(119, 1, 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', '2021-03-20 10:06:32', '2021-07-28 14:45:35', 'Franz', 'Tris'),
(66, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2021-09-11 09:32:59', '2021-03-17 01:22:39', 'Tony', 'Ikey'),
(36, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-03-04 17:43:07', '2021-10-08 16:20:32', 'Rees', 'Hubey'),
(104, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-07-11 18:23:15', '2021-06-09 13:23:03', 'Hall', 'Rollie'),
(63, 1, 'Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '2021-06-26 18:57:48', '2021-06-30 23:24:08', 'Keir', 'Ky'),
(99, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-10-03 02:36:13', '2021-11-27 11:12:43', 'Georgi', 'Thane'),
(17, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-07-19 19:04:40', '2021-06-30 19:59:12', 'Oliver', 'Jarrad'),
(33, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-03-19 04:18:04', '2021-11-28 06:15:06', 'Elvin', 'Sunny'),
(102, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-11-28 18:39:57', '2021-06-24 11:01:37', 'Fax', 'Jayme'),
(28, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2021-08-03 06:01:12', '2021-03-12 08:58:02', 'Eldon', 'Emory'),
(37, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-05-31 02:48:41', '2021-10-21 23:00:17', 'Northrup', 'Bart'),
(75, 1, 'Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '2021-03-11 21:47:46', '2021-04-19 14:10:05', 'Timmie', 'Roma'),
(70, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2021-10-30 16:41:56', '2021-09-06 14:43:59', 'Maximo', 'Eziechiele'),
(53, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-06-09 22:28:41', '2022-01-20 12:47:05', 'Myrvyn', 'Faulkner'),
(33, 1, 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '2021-11-18 08:10:04', '2021-10-15 12:18:35', 'Milty', 'Gordie'),
(41, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-05-05 07:39:10', '2021-03-17 04:48:00', 'Guillaume', 'Holt'),
(103, 1, 'Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '2021-07-16 03:33:44', '2021-12-27 03:33:26', 'Cyrille', 'Ruprecht'),
(7, 1, 'Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', '2022-01-04 16:06:48', '2021-06-11 14:41:17', 'Jervis', 'Base'),
(26, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2022-01-09 16:07:10', '2021-07-25 22:44:28', 'Nikolos', 'Stanly'),
(8, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2021-02-14 01:02:43', '2022-01-10 03:11:26', 'Stefano', 'Hillel'),
(58, 1, 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '2021-02-27 03:57:38', '2021-10-16 02:36:54', 'Flinn', 'Pembroke'),
(87, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-06-17 04:52:04', '2021-09-29 05:08:41', 'Tome', 'Nat'),
(11, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-06-20 03:31:09', '2021-08-09 08:07:50', 'Garrick', 'Bailey'),
(103, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2022-01-15 03:35:49', '2021-08-19 05:46:11', 'Fonz', 'Mohandas'),
(119, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-10-19 22:27:28', '2021-03-18 00:32:07', 'Swen', 'My'),
(33, 1, 'Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '2022-01-23 21:02:14', '2021-07-22 18:04:02', 'Klement', 'Giordano'),
(118, 1, 'Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.', '2021-12-25 15:45:04', '2021-07-25 01:53:41', 'Alister', 'Gavan'),
(87, 1, 'Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '2021-03-13 11:05:05', '2021-04-24 11:01:30', 'Scotty', 'Pascal'),
(95, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-08-21 20:13:53', '2021-05-28 10:09:16', 'Clevey', 'Bailey'),
(48, 1, 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '2021-12-28 19:03:27', '2021-07-19 05:47:56', 'Grantham', 'Hadrian'),
(27, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2021-09-08 06:14:44', '2021-03-08 01:09:46', 'Gardner', 'Zolly'),
(93, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-11-17 23:36:20', '2021-04-14 08:16:21', 'Jerome', 'Dev'),
(11, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-06-13 21:19:56', '2021-10-29 10:51:51', 'Lincoln', 'Erwin'),
(68, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-08-30 18:51:16', '2021-04-04 13:02:51', 'Sky', 'Lindon'),
(103, 1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '2021-05-25 13:40:27', '2021-07-08 18:29:16', 'Bary', 'Arri'),
(109, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-06-13 00:58:44', '2021-11-02 14:32:58', 'Rafael', 'Ivor'),
(86, 1, 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '2022-01-25 01:28:11', '2021-04-17 01:10:19', 'Mathe', 'Mattie'),
(70, 1, 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '2021-04-12 21:18:27', '2021-07-01 12:03:21', 'Geoffrey', 'Tadeo'),
(37, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-06-21 12:34:50', '2021-03-09 11:05:09', 'Powell', 'Winifield'),
(82, 1, 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '2021-10-31 08:16:23', '2021-03-23 18:55:47', 'Winifield', 'Rolando'),
(69, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2021-03-29 13:14:38', '2021-03-23 01:58:27', 'Giordano', 'Averell'),
(23, 1, 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', '2021-05-20 07:38:20', '2021-08-05 13:35:48', 'Lammond', 'Martie'),
(53, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-02-02 22:43:50', '2021-03-21 01:18:12', 'Tades', 'Jedidiah'),
(21, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-05-29 06:29:02', '2021-10-13 02:23:19', 'Germayne', 'Jermayne'),
(94, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-06-02 12:21:13', '2021-09-03 15:17:13', 'Gregory', 'Woodrow'),
(9, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2021-06-07 05:33:53', '2021-04-26 03:00:50', 'Theodore', 'Godwin'),
(74, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-11-22 01:27:42', '2021-12-07 13:24:52', 'Richy', 'Garvin'),
(93, 1, 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '2021-11-29 14:10:08', '2021-12-21 15:41:28', 'Skipp', 'Broderick'),
(66, 1, 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '2021-07-18 13:45:38', '2021-09-07 10:37:11', 'Kaine', 'Rooney'),
(46, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-09-08 17:42:59', '2021-08-28 15:12:30', 'Humfrid', 'Steffen'),
(26, 1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '2022-01-22 19:23:45', '2021-04-19 07:53:02', 'Jamie', 'Reinaldos'),
(2, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-02-23 17:42:56', '2021-10-09 08:03:13', 'Glynn', 'Truman'),
(15, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-10-12 14:19:16', '2021-09-11 22:13:27', 'Maddy', 'Tynan'),
(96, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-12-27 11:42:15', '2022-01-19 14:11:02', 'Merill', 'Kermit'),
(118, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2021-07-30 23:57:48', '2021-11-13 11:45:31', 'Llewellyn', 'Welch'),
(118, 1, 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.', '2021-07-21 15:39:09', '2021-10-24 12:13:07', 'Augustine', 'Cash'),
(82, 1, 'Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.', '2021-04-10 22:46:57', '2021-10-07 06:49:09', 'Jermain', 'Felice'),
(17, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-02-10 12:15:50', '2021-02-08 21:36:20', 'Ned', 'Marlow'),
(118, 1, 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '2021-04-28 19:26:22', '2021-04-01 16:32:22', 'Griswold', 'Brion'),
(37, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-04-23 15:49:37', '2021-12-14 18:20:38', 'Lemuel', 'Karel'),
(60, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-08-14 16:26:15', '2021-07-05 14:35:38', 'Yance', 'Henderson'),
(114, 1, 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '2021-05-20 19:07:27', '2022-01-26 17:02:57', 'Munroe', 'Olvan'),
(20, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-08-30 20:30:28', '2021-09-11 10:18:50', 'Salim', 'Keene'),
(51, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-03-08 12:55:54', '2021-07-12 23:56:12', 'Rustie', 'Lorne'),
(50, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-10-13 17:57:44', '2021-05-10 21:31:48', 'Lorry', 'Alex'),
(43, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-04-02 01:37:13', '2021-09-16 05:24:04', 'Leonidas', 'Fulton'),
(115, 1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '2021-11-11 04:39:17', '2021-11-03 15:21:42', 'Marietta', 'Brnaba'),
(97, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-01-31 06:45:18', '2021-03-10 22:17:41', 'Obie', 'Allard'),
(8, 1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '2021-08-25 23:41:07', '2021-04-19 09:14:12', 'Dru', 'Osborn'),
(11, 1, 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '2021-11-28 19:55:06', '2021-09-22 19:59:06', 'Iain', 'Job'),
(43, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-09-29 14:30:08', '2021-04-05 17:41:49', 'Rikki', 'Hymie'),
(31, 1, 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '2021-10-05 20:08:45', '2021-10-31 14:59:42', 'Em', 'Aldric'),
(88, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-03-27 00:02:27', '2021-12-17 06:02:34', 'Burty', 'Martainn'),
(56, 1, 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '2021-12-22 12:41:15', '2021-04-14 03:12:08', 'Garvin', 'Esra'),
(9, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-05-29 13:08:55', '2021-08-01 08:38:29', 'Siward', 'Garey'),
(31, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-12-15 19:49:25', '2022-01-27 19:49:47', 'Fran', 'Cece'),
(1, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-03-02 11:57:54', '2021-05-09 12:36:08', 'Torry', 'Rolando'),
(110, 1, 'In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.', '2021-07-27 01:40:15', '2021-06-25 16:54:44', 'Kevin', 'Chico'),
(78, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-03-30 22:33:45', '2021-03-13 12:40:17', 'Xavier', 'Nicol'),
(73, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-11-26 19:26:39', '2021-04-14 20:32:25', 'Grannie', 'Cobbie'),
(20, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-06-30 06:56:10', '2021-02-25 03:34:01', 'Haskell', 'Terence'),
(99, 1, 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '2021-07-27 20:53:45', '2021-03-13 15:29:58', 'Nealy', 'Doyle'),
(58, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-08-04 21:54:34', '2021-05-17 14:36:46', 'Sibyl', 'Consalve'),
(33, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2021-08-12 10:07:09', '2021-02-14 00:36:15', 'Arvy', 'Tymothy'),
(111, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-09-16 06:12:57', '2021-09-04 15:51:30', 'Morten', 'Gerhard'),
(83, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-12-16 10:24:39', '2021-02-25 21:15:30', 'Sheridan', 'Cash'),
(13, 1, 'In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.', '2021-09-25 16:26:15', '2021-09-04 06:36:17', 'Heath', 'Irwinn'),
(47, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-02-15 09:00:36', '2021-12-02 02:50:19', 'Bordy', 'Kliment'),
(37, 1, 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '2021-08-08 15:11:06', '2021-05-31 22:32:58', 'Graeme', 'Cody'),
(19, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-01-29 18:57:18', '2021-10-01 12:57:33', 'Ram', 'Gino'),
(9, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-12-31 02:29:25', '2021-02-04 09:29:05', 'Umberto', 'Timotheus'),
(3, 1, 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.', '2021-09-01 13:11:45', '2021-10-28 14:30:23', 'Juan', 'Forest'),
(97, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-12-19 15:39:54', '2021-07-10 04:11:12', 'Urbanus', 'Noach'),
(88, 1, 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '2021-11-12 11:38:06', '2021-12-13 15:21:53', 'Zack', 'Jammal'),
(20, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-10-20 18:22:32', '2021-07-10 16:15:54', 'Norrie', 'Barny'),
(93, 1, 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', '2021-09-08 08:49:05', '2021-02-27 04:15:27', 'Donn', 'Adan'),
(61, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-06-24 16:06:45', '2021-10-31 08:38:22', 'Paxton', 'Stevy'),
(73, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-03-11 20:20:34', '2021-04-19 22:24:56', 'Carolus', 'Niven'),
(60, 1, 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '2021-10-12 16:46:55', '2021-05-08 14:42:18', 'Cameron', 'Beniamino'),
(41, 1, 'Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.', '2021-03-16 05:38:39', '2021-02-26 21:41:53', 'Flint', 'Artur'),
(116, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-08-15 22:55:29', '2021-09-22 03:03:29', 'Efren', 'Carrol'),
(113, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-06-13 10:25:18', '2021-10-27 10:34:16', 'Nevins', 'Caspar'),
(86, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-04-12 11:14:15', '2021-02-13 09:33:29', 'Carrol', 'Isac'),
(122, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-11-30 20:48:06', '2021-02-19 12:25:33', 'Dagny', 'Silvain'),
(42, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-09-29 09:08:16', '2021-01-29 16:01:20', 'Thurstan', 'Vidovic'),
(3, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-02-10 03:27:32', '2021-11-07 23:23:44', 'Jerrold', 'Mac'),
(92, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-09-24 15:03:04', '2021-03-09 13:36:02', 'Tommie', 'Uriel'),
(3, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2021-03-18 14:50:37', '2021-04-25 15:04:11', 'Desi', 'Patrizius'),
(24, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-04-26 17:14:34', '2021-07-04 04:58:06', 'Frederigo', 'Heath'),
(62, 1, 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '2021-07-30 17:36:48', '2021-02-22 02:50:31', 'Conroy', 'Ralf'),
(49, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-06-30 07:55:25', '2021-05-01 04:31:05', 'Carolus', 'Kiley'),
(11, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-11-30 02:55:08', '2021-12-17 10:25:02', 'Killian', 'Ewell'),
(3, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-10-17 05:31:12', '2021-12-19 13:25:46', 'Gary', 'Korey'),
(89, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-05-16 00:33:39', '2021-04-21 11:16:34', 'Jeth', 'Shem'),
(104, 1, 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '2021-04-11 19:12:30', '2021-07-28 21:58:46', 'Archambault', 'Elwyn'),
(120, 1, 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '2021-11-09 07:48:20', '2021-05-25 01:18:53', 'Owen', 'Aldrich'),
(119, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-12-11 18:39:03', '2021-05-29 15:07:40', 'Fleming', 'Kaine'),
(71, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-09-22 10:07:58', '2021-06-29 20:27:29', 'Gianni', 'Leroi'),
(45, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-06-03 15:54:44', '2022-01-21 14:50:05', 'Saundra', 'Timofei'),
(78, 1, 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '2021-05-19 04:22:01', '2021-02-23 20:41:21', 'Raphael', 'Earl'),
(29, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-02-14 18:22:02', '2021-03-16 18:55:35', 'Thorstein', 'Boycie'),
(14, 1, 'Nullam sit amet turpis elementum ligula vehicula consequat. Morbi a ipsum. Integer a nibh.', '2021-12-12 21:27:12', '2022-01-13 21:51:23', 'Haywood', 'Orland'),
(36, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-12-04 23:26:12', '2021-06-24 00:39:21', 'Arley', 'Bealle'),
(16, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-10-20 22:49:39', '2021-09-16 21:40:00', 'Gerik', 'Tom'),
(30, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-04-22 18:41:14', '2021-02-14 23:42:46', 'Kimbell', 'Avigdor'),
(119, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-11-05 20:30:44', '2021-08-23 04:17:55', 'Manny', 'Roth'),
(49, 1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '2021-03-30 20:19:39', '2021-11-11 18:15:08', 'Clare', 'Frants'),
(53, 1, 'Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', '2021-07-25 16:59:57', '2021-12-26 16:40:39', 'Verge', 'Uriel'),
(58, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-10-24 00:02:07', '2021-05-14 21:38:51', 'Tobe', 'Padraig'),
(97, 1, 'Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '2021-03-15 03:17:22', '2021-03-09 07:40:08', 'Tommy', 'Stanton'),
(58, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-02-17 15:44:23', '2021-05-12 19:09:44', 'Addy', 'Georas'),
(18, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2022-01-14 07:16:57', '2022-01-18 13:43:16', 'Salem', 'Franklin'),
(48, 1, 'In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.', '2021-03-25 20:09:14', '2021-06-05 06:26:54', 'Wang', 'Gunner'),
(1, 1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '2021-10-28 04:52:36', '2021-12-25 06:43:01', 'Brendan', 'Rouvin'),
(102, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-06-13 23:00:54', '2021-03-02 16:25:07', 'Bran', 'Chet'),
(105, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-07-23 01:10:10', '2021-10-09 04:58:11', 'My', 'Conny'),
(1, 1, 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '2021-06-15 07:11:35', '2021-11-10 07:57:55', 'Raimondo', 'Lou'),
(87, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-04-12 09:26:39', '2021-02-05 04:29:18', 'Curry', 'Gian'),
(113, 1, 'Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.', '2021-04-14 23:17:12', '2021-12-21 20:18:49', 'Raleigh', 'Marlon'),
(74, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-10-26 17:58:35', '2022-01-27 11:45:17', 'Lauren', 'Hoebart'),
(28, 1, 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '2021-05-17 07:57:54', '2021-03-16 07:48:16', 'Tonnie', 'Borden'),
(47, 1, 'Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius.', '2021-07-30 20:29:36', '2021-12-29 07:52:24', 'Galvin', 'Olenolin'),
(104, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-07-16 13:21:55', '2021-02-18 15:51:26', 'Burty', 'Nicky'),
(121, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-02-02 04:12:07', '2021-12-07 02:32:36', 'Ashton', 'Galvin'),
(12, 1, 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '2021-10-18 21:01:27', '2021-10-02 00:45:14', 'Pacorro', 'Johan'),
(62, 1, 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '2021-02-26 12:57:07', '2021-05-28 13:25:39', 'Chip', 'Lazaro'),
(3, 1, 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.', '2021-08-09 03:26:07', '2021-11-24 20:01:46', 'Odey', 'Alasdair'),
(111, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-09-11 06:11:36', '2021-02-08 18:50:27', 'Francis', 'Clywd'),
(15, 1, 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '2021-10-28 03:52:43', '2021-05-07 04:46:57', 'Ambros', 'Allistir'),
(63, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-02-26 11:44:06', '2021-04-04 10:50:51', 'Godwin', 'Darn'),
(64, 1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '2021-09-18 01:26:49', '2021-10-18 22:02:35', 'Saw', 'Hersch'),
(75, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-05-07 22:15:22', '2021-04-09 04:53:46', 'Jonas', 'Walther'),
(115, 1, 'Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', '2022-01-09 09:24:31', '2021-11-23 05:50:30', 'Maison', 'Rutledge'),
(66, 1, 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '2021-04-29 15:50:03', '2021-10-09 05:24:40', 'Warde', 'Ezra'),
(113, 1, 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '2021-11-27 02:08:50', '2021-09-17 23:44:27', 'Beale', 'John'),
(22, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-12-07 04:27:25', '2021-08-01 16:35:36', 'Stephanus', 'Woodie'),
(101, 1, 'Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.', '2022-01-09 23:00:02', '2021-02-03 16:50:34', 'Kendrick', 'Stevie'),
(74, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-11-13 17:40:36', '2021-05-24 19:48:38', 'Renato', 'Lazar'),
(117, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-04-07 23:37:24', '2021-07-31 23:54:24', 'Clim', 'Kerwin'),
(109, 1, 'Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.', '2021-06-01 10:19:17', '2021-05-05 01:35:40', 'Merry', 'Alejoa'),
(35, 1, 'Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis.', '2021-07-26 04:44:47', '2021-08-04 20:39:24', 'Hank', 'Bronnie'),
(58, 1, 'Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.', '2021-06-05 17:56:40', '2021-12-16 06:08:45', 'Pembroke', 'Rudolfo'),
(94, 1, 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '2021-07-27 15:28:41', '2021-02-03 15:56:24', 'Skye', 'Travus'),
(110, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-05-13 08:24:45', '2021-11-05 10:30:53', 'Anatole', 'Josh'),
(38, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2022-01-03 09:28:12', '2021-06-15 10:09:44', 'Wolfy', 'Denver'),
(112, 1, 'In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.', '2021-10-28 06:09:00', '2021-04-18 09:32:47', 'Ave', 'Samson'),
(55, 1, 'Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.', '2021-03-30 07:04:00', '2021-06-11 23:16:21', 'Merrick', 'Taddeo'),
(38, 1, 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '2021-05-12 15:07:01', '2021-03-01 11:26:25', 'Lamar', 'Denver'),
(57, 1, 'Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.', '2021-07-19 19:58:41', '2022-01-09 10:16:22', 'Marc', 'Dudley'),
(110, 1, 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '2021-10-10 12:35:10', '2021-06-08 16:03:44', 'Cirilo', 'Hewie'),
(16, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-09-15 20:31:58', '2021-09-10 04:08:45', 'Parnell', 'Justen'),
(77, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-10-10 05:06:58', '2021-03-07 18:41:41', 'Wait', 'Jefferey'),
(80, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-11-29 14:56:54', '2021-08-11 08:38:14', 'Oliver', 'Gordan'),
(93, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2021-08-08 12:08:41', '2021-02-21 14:20:28', 'Boy', 'Erhard'),
(21, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-02-02 10:37:42', '2021-07-07 09:13:50', 'Kingsley', 'Cristiano'),
(121, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-05-01 16:02:15', '2021-03-16 04:57:53', 'Jack', 'Emerson'),
(81, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-10-06 07:22:15', '2021-04-13 18:38:19', 'Shadow', 'Olivero'),
(115, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-08-21 18:30:28', '2022-01-27 04:56:23', 'Torrance', 'Jay'),
(71, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-07-14 22:27:52', '2021-12-20 14:06:44', 'Griz', 'Rice'),
(10, 1, 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '2021-09-22 03:34:12', '2021-08-02 23:30:33', 'Johnathan', 'Gasper'),
(83, 1, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.', '2021-11-09 09:44:05', '2021-09-27 16:32:41', 'Krishnah', 'Gauthier'),
(65, 1, 'Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.', '2021-06-05 10:03:50', '2021-04-03 21:14:02', 'Padraig', 'Hagan'),
(65, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-02-08 03:59:27', '2022-01-05 18:54:29', 'Marven', 'Cesaro'),
(40, 1, 'Fusce consequat. Nulla nisl. Nunc nisl.', '2021-09-10 06:18:43', '2022-01-05 12:44:51', 'Iggy', 'Giffer'),
(40, 1, 'Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.', '2021-11-24 21:14:01', '2021-07-24 00:45:50', 'Tanner', 'Alasdair'),
(53, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-04-30 20:09:55', '2021-07-19 23:40:23', 'Germain', 'Raffaello'),
(35, 1, 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.', '2021-09-23 19:49:04', '2021-07-17 12:46:19', 'Pat', 'Lynn'),
(108, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-02-26 17:41:27', '2021-06-19 13:50:02', 'Ancell', 'Zack'),
(123, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-04-02 23:38:41', '2021-05-25 09:51:50', 'Augustus', 'Noak'),
(10, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-08-04 16:14:43', '2021-05-14 16:24:37', 'Verne', 'Jae'),
(70, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-11-06 06:46:35', '2022-01-10 16:32:48', 'Guillermo', 'Donavon'),
(66, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2022-01-14 20:49:05', '2021-02-17 00:51:12', 'Ermin', 'Eugenius'),
(60, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-10-31 12:14:52', '2021-12-16 14:05:55', 'Beniamino', 'Lucius'),
(86, 1, 'Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.', '2021-05-14 17:45:54', '2021-11-04 17:25:01', 'Roman', 'Pippo'),
(46, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-12-30 18:54:39', '2021-10-27 17:51:06', 'Laird', 'Rooney'),
(109, 1, 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '2021-02-15 22:55:20', '2021-05-19 06:29:30', 'Harwell', 'Hamish'),
(29, 1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '2021-03-03 14:41:45', '2021-08-21 19:45:03', 'Farrell', 'Putnam'),
(4, 1, 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.', '2021-05-07 23:41:49', '2021-07-20 15:05:46', 'Cullan', 'Brenden'),
(72, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2022-01-21 09:58:07', '2021-09-30 10:22:58', 'Reinhard', 'Gustav'),
(103, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-06-21 04:54:38', '2021-02-04 14:03:34', 'Redford', 'Odey'),
(3, 1, 'Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.', '2021-07-03 22:53:01', '2021-12-17 02:16:19', 'Onofredo', 'Burnard'),
(47, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-04-14 07:12:05', '2022-01-25 09:31:18', 'Ludwig', 'Bink'),
(108, 1, 'Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '2021-01-29 06:11:21', '2021-11-28 10:36:30', 'Brose', 'Dory'),
(18, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-07-11 22:57:32', '2021-12-29 13:13:47', 'Jorgan', 'Tully'),
(122, 1, 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '2021-07-07 11:28:36', '2022-01-11 22:25:11', 'Noak', 'Randi'),
(10, 1, 'Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum.', '2021-01-28 04:18:05', '2021-03-15 00:49:20', 'Robers', 'Lucien'),
(100, 1, 'In quis justo. Maecenas rhoncus aliquam lacus. Morbi quis tortor id nulla ultrices aliquet.', '2021-10-21 10:15:11', '2021-07-15 02:29:24', 'Ellwood', 'Haley'),
(109, 1, 'In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.', '2021-09-20 02:30:44', '2021-02-23 21:10:19', 'Rand', 'Farr'),
(7, 1, 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '2021-03-30 03:51:17', '2021-03-12 03:31:28', 'Benn', 'Felicio'),
(3, 1, 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '2021-09-28 17:14:00', '2021-11-10 07:58:33', 'Bram', 'Reamonn'),
(19, 1, 'Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.', '2021-11-21 02:15:09', '2021-09-26 07:25:00', 'Tobiah', 'Elvyn'),
(29, 1, 'Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.', '2021-06-17 22:45:24', '2021-02-22 00:27:48', 'Tuckie', 'Alano'),
(38, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-03-08 06:05:41', '2021-08-23 14:39:11', 'Torrey', 'Lincoln'),
(89, 1, 'Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.', '2021-05-02 07:48:14', '2021-04-21 23:59:10', 'Sheppard', 'Mordy'),
(37, 1, 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '2021-09-23 10:38:38', '2021-09-28 17:28:23', 'Alasteir', 'Rodolph'),
(96, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-12-13 02:05:08', '2021-08-13 20:19:31', 'Curcio', 'Frankie'),
(9, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-08-03 08:05:59', '2021-07-18 13:07:29', 'Randal', 'Lowrance'),
(95, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-05-23 16:26:14', '2022-01-27 15:13:11', 'Corbin', 'Gardy'),
(41, 1, 'In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.', '2021-04-12 18:28:56', '2021-09-16 06:18:28', 'Sammie', 'Jerrold'),
(80, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-02-20 22:12:07', '2021-05-20 15:04:18', 'Abram', 'Foster'),
(46, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-02-05 14:12:10', '2021-04-21 22:37:57', 'Rusty', 'Martin'),
(117, 1, 'Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.', '2021-08-30 23:52:53', '2021-04-13 04:02:26', 'Mohammed', 'Roman'),
(117, 1, 'Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.', '2021-11-28 01:58:02', '2021-12-21 11:52:52', 'Tomas', 'Lorry'),
(102, 1, 'Curabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.', '2021-02-07 07:54:20', '2022-01-26 07:40:14', 'Laurence', 'Obediah'),
(105, 1, 'Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.', '2021-12-07 21:09:27', '2021-02-25 05:08:10', 'Doyle', 'Manolo'),
(31, 1, 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '2021-06-08 17:54:29', '2021-04-09 21:42:54', 'Alfons', 'Merrel'),
(104, 1, 'Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo. In blandit ultrices enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '2021-02-15 00:43:19', '2021-05-11 00:01:36', 'Barris', 'Thayne'),
(6, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-08-23 18:08:15', '2021-02-14 18:46:55', 'Chester', 'Raimund'),
(23, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-08-22 05:10:51', '2021-11-14 05:48:36', 'Gunner', 'Daryle'),
(9, 1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '2021-07-08 21:49:32', '2021-10-16 05:19:59', 'Garey', 'Newton'),
(61, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-02-16 21:02:31', '2021-03-14 09:32:46', 'Pryce', 'Ruggiero'),
(60, 1, 'Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.', '2021-07-01 14:11:02', '2022-01-05 14:35:41', 'Alphonse', 'Jimmie'),
(66, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-07-21 22:00:47', '2021-04-15 01:34:52', 'Francesco', 'Sigismond'),
(110, 1, 'Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.', '2022-01-20 13:04:44', '2021-07-23 13:46:46', 'Lee', 'Hillie'),
(49, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-08-17 22:15:55', '2021-08-14 18:08:06', 'Xerxes', 'Gavan'),
(30, 1, 'Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.', '2022-01-01 09:01:26', '2021-02-05 06:06:11', 'Nilson', 'Abramo'),
(66, 1, 'Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.', '2021-03-19 18:31:00', '2021-02-02 18:13:43', 'Efrem', 'Nappie'),
(20, 1, 'Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.', '2021-08-10 09:50:08', '2021-06-10 09:21:44', 'Killy', 'Link'),
(60, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-07-01 11:17:44', '2021-06-12 14:47:11', 'Redd', 'Findlay'),
(84, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-11-20 19:24:29', '2021-07-09 22:30:51', 'Jermaine', 'Giordano'),
(16, 1, 'Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.', '2021-03-31 15:02:53', '2022-01-27 10:41:22', 'Nevins', 'Tades'),
(24, 1, 'Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.', '2021-12-14 16:08:30', '2021-07-27 17:14:42', 'Ford', 'Bert'),
(118, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-04-06 13:22:24', '2021-03-22 21:55:23', 'Derward', 'Gilberto'),
(80, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-11-11 14:40:19', '2021-03-18 04:28:34', 'Raynard', 'Harmon'),
(15, 1, 'Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis.', '2021-08-03 10:39:41', '2021-10-10 14:36:42', 'Link', 'Herculie'),
(53, 1, 'Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.', '2021-10-16 21:35:19', '2021-02-03 11:50:26', 'Bruno', 'Morry'),
(116, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-06-30 09:33:06', '2021-03-14 15:57:56', 'Ash', 'Kain'),
(18, 1, 'Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.', '2021-12-17 04:35:08', '2021-12-03 02:48:23', 'Vance', 'Sherwood'),
(39, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2022-01-24 11:08:07', '2021-03-10 17:24:44', 'Alexio', 'Zak'),
(36, 1, 'Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.', '2021-10-26 14:32:13', '2021-12-09 16:40:34', 'Gustavus', 'Dennis'),
(95, 1, 'Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.', '2022-01-04 18:07:58', '2021-06-09 11:32:21', 'Correy', 'Michale'),
(83, 1, 'Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.', '2021-08-26 19:21:23', '2021-08-18 00:16:06', 'Marsh', 'Jake'),
(32, 1, 'Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem.', '2021-04-06 03:33:13', '2021-02-08 18:06:28', 'Joey', 'Jeddy'),
(97, 1, 'Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.', '2021-10-02 12:32:35', '2021-03-31 17:12:09', 'Ermin', 'Randy'),
(101, 1, 'In congue. Etiam justo. Etiam pretium iaculis justo.', '2021-06-26 12:29:52', '2021-01-29 02:54:16', 'Archer', 'Denney'),
(109, 1, 'Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.', '2021-05-01 12:24:18', '2021-05-30 21:29:42', 'Fransisco', 'Francisco'),
(93, 1, 'Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.', '2021-02-22 10:56:34', '2021-09-02 15:20:32', 'Georgy', 'Wells'),
(118, 1, 'Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.', '2021-11-04 07:35:10', '2021-12-24 13:17:12', 'Oates', 'Clayborne'),
(97, 1, 'Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.', '2021-07-18 10:42:20', '2021-12-25 13:59:02', 'Richmound', 'Wilmar'),
(6, 1, 'Phasellus in felis. Donec semper sapien a libero. Nam dui.', '2021-02-08 10:45:24', '2021-04-04 03:18:49', 'Rees', 'Kerk'),
(106, 1, 'Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.', '2021-02-12 12:56:15', '2021-06-19 00:23:26', 'Kiley', 'Keenan'),
(77, 1, 'Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.', '2022-01-08 02:32:10', '2021-07-23 12:21:01', 'Harlen', 'Zacharia'),
(56, 1, 'Sed ante. Vivamus tortor. Duis mattis egestas metus.', '2021-11-18 01:32:48', '2021-06-06 01:59:25', 'Vittorio', 'Milty'),
(19, 1, 'In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.', '2021-05-07 23:57:29', '2021-04-03 21:55:11', 'Oliver', 'Graehme')
;

View File

@@ -0,0 +1,70 @@
/* 검색창 */
.search-form {
width: 80%;
margin: 0 auto;
margin-top: 1rem;
}
.search-form input {
height: 100%;
background: transparent;
border: 0;
display: block;
width: 100%;
padding: 1rem;
height: 100%;
font-size: 1rem;
}
.search-form select {
background: transparent;
border: 0;
padding: 1rem;
height: 100%;
font-size: 1rem;
}
.search-form select:focus {
border: 0;
}
.search-form button {
height: 100%;
width: 100%;
font-size: 1rem;
}
.search-form button svg {
width: 24px;
height: 24px;
}
.card-margin {
margin-bottom: 1.875rem;
}
@media (min-width: 992px) {
.col-lg-2 {
flex: 0 0 16.66667%;
max-width: 16.66667%;
}
}
.card {
border: 0;
box-shadow: 0px 0px 10px 0px rgba(82, 63, 105, 0.1);
-webkit-box-shadow: 0px 0px 10px 0px rgba(82, 63, 105, 0.1);
-moz-box-shadow: 0px 0px 10px 0px rgba(82, 63, 105, 0.1);
-ms-box-shadow: 0px 0px 10px 0px rgba(82, 63, 105, 0.1);
}
.card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #ffffff;
background-clip: border-box;
border: 1px solid #e6e4e9;
border-radius: 8px;
}

View File

@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="Bobby">
<title>게시글 페이지</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
<header id="header"></header>
<main class="container">
<header class="py-5 text-center">
<h1>첫번째 글</h1>
</header>
<div class="row g-5">
<section class="col-md-5 col-lg-4 order-md-last">
<aside>
<p><span class="nick-name">Bobby</span></p>
<p><a class="u-url" rel="me" href="mailto:haerong22@gmail.com">bobby@mail.com</a></p>
<p><time datetime="2022-01-01T00:00:00">2022-08-12</time></p>
<p>#java</p>
</aside>
</section>
<article class="col-md-7 col-lg-8">
<p>본문<br><br></p>
</article>
</div>
<div class="row g-5">
<section>
<form class="row g-3">
<div class="col-8">
<label for="comment-textbox" hidden>댓글</label>
<textarea class="form-control" id="comment-textbox" placeholder="댓글 쓰기.." rows="3"></textarea>
</div>
<div class="col-auto">
<label for="comment-submit" hidden>댓글 쓰기</label>
<button class="btn btn-primary" id="comment-submit" type="submit">쓰기</button>
</div>
</form>
<ul>
<li>
<div>
<time><small>2022-08-12</small></time>
<strong>Bobby</strong>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br>
Lorem ipsum dolor sit amet
</p>
</div>
</li>
<li>
<div>
<time><small>2022-08-12</small></time>
<strong>Bobby</strong>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br>
Lorem ipsum dolor sit amet
</p>
</div>
</li>
</ul>
</section>
</div>
<div class="row g-5">
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">&laquo; prev</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">next &raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
</main>
<footer id="footer"></footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<thlogic>
<attr sel="#header" th:replace="header :: header" />
<attr sel="#footer" th:replace="footer :: footer" />
</thlogic>

View File

@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="bobby">
<title>게시판 페이지</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<link href="/css/search-bar.css" rel="stylesheet">
</head>
<body>
<header id="header">
헤더
<hr>
</header>
<main class="container">
<div class="row">
<div class="card card-margin search-form">
<div class="card-body p-0">
<form id="card search-form">
<div class="row">
<div class="col-12">
<div class="row no-gutters">
<div class="col-lg-3 col-md-3 col-sm-12 p-0">
<label for="search-type" hidden>검색 유형</label>
<select class="form-control" id="search-type">
<option>제목</option>
<option>본문</option>
<option>id</option>
<option>닉네임</option>
<option>해시태그</option>
</select>
</div>
<div class="col-lg-8 col-md-6 col-sm-12 p-0">
<label for="search-value" hidden>검색어</label>
<input type="text" placeholder="검색어..." class="form-control" id="search-value" name="search-value">
</div>
<div class="col-lg-1 col-md-3 col-sm-12 p-0">
<button type="submit" class="btn btn-base">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<table class="table" id="article-table">
<thead>
<tr>
<th class="title col-6">제목</th>
<th class="hashtag col-2">해시태그</th>
<th class="user-id col">작성자</th>
<th class="created-at col">작성일</th>
</tr>
</thead>
<tbody>
<tr>
<td class="title"><a>첫 글</a></td>
<td class="hashtag">#Java</td>
<td class="user-id">kim</td>
<td class="created-at"><time>2022-08-09</time></td>
</tr>
<tr>
<td>두번째 글</td>
<td>#Spring</td>
<td>kim</td>
<td>2022-08-09</td>
</tr>
<tr>
<td>세번째 글</td>
<td>#Mysql</td>
<td>kim</td>
<td>2022-08-09</td>
</tr>
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</nav>
</main>
<footer id="footer">
<hr>
푸터
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<thlogic>
<attr sel="#header" th:replace="header :: header" />
<attr sel="#footer" th:replace="footer :: footer" />
<attr sel="#article-table">
<attr sel="tbody" th:remove="all-but-first">
<attr sel="tr[0]" th:each="article : ${articles}">
<attr sel="td.title/a" th:text="${article.title}" th:href="@{'/articles/' + ${article.id}}" />
<attr sel="td.hashtag" th:text="${article.hashtag}" />
<attr sel="td.user-id" th:text="${article.nickname}" />
<attr sel="td.created-at/time" th:datetime="${article.createdAt}" th:text="${#temporals.format(article.createdAt, 'yyyy-MM-dd')}"/>
</attr>
</attr>
</attr>
</thlogic>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Footer Template</title>
</head>
<body>
<footer class="container d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<p class="col-md-4 mb-0 text-muted">&copy; 2022 Bobby, Inc</p>
<ul class="nav col-md-4 justify-content-end">
<li class="nav-item"><a href="/" class="nav-link px-2 text-muted">Home</a></li>
</ul>
</footer>
</body>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Header Template</title>
</head>
<body>
<header class="p-3 bg-dark text-white">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="/" class="nav-link px-2 text-secondary">Home</a></li>
</ul>
<div class="text-end">
<button type="button" class="btn btn-outline-light me-2">Login</button>
<button type="button" class="btn btn-warning">Sign-up</button>
</div>
</div>
</div>
</header>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,13 @@
package com.example.board;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class BoardApplicationTests {
@Test
void contextLoads() {
}
}

View File

@@ -0,0 +1,135 @@
package com.example.board.controller;
import com.example.board.config.SecurityConfig;
import com.example.board.dto.ArticleWithCommentsDto;
import com.example.board.dto.UserAccountDto;
import com.example.board.service.ArticleService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDateTime;
import java.util.Set;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@DisplayName("View 컨트롤러 - 게시글")
@Import(SecurityConfig.class)
@WebMvcTest(ArticleController.class)
class ArticleControllerTest {
private final MockMvc mockMvc;
@MockBean
private ArticleService articleService;
public ArticleControllerTest(@Autowired MockMvc mockMvc) {
this.mockMvc = mockMvc;
}
@DisplayName("[view][GET] 게시글 리스트(게시판) 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticlesView_thenReturnsArticlesView() throws Exception {
// given
given(articleService.searchArticles(eq(null), eq(null), any(Pageable.class)))
.willReturn(Page.empty());
// when & then
mockMvc.perform(get("/articles"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(view().name("articles/index"))
.andExpect(model().attributeExists("articles"))
;
then(articleService).should().searchArticles(eq(null), eq(null), any(Pageable.class));
}
@DisplayName("[view][GET] 게시글 상세 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleView_thenReturnsArticleView() throws Exception {
// given
Long articleId = 1L;
given(articleService.getArticle(articleId)).willReturn(createArticleWithCommentDto());
// when & then
mockMvc.perform(get("/articles/" + articleId))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(view().name("articles/detail"))
.andExpect(model().attributeExists("article"))
.andExpect(model().attributeExists("articleComments"))
;
then(articleService).should().getArticle(articleId);
}
@Disabled("구현 중")
@DisplayName("[view][GET] 게시글 검색 전용 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleSearchView_thenReturnsArticleSearchView() throws Exception {
// given
// when & then
mockMvc.perform(get("/articles/search"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(view().name("articles/search"))
;
}
@Disabled("구현 중")
@DisplayName("[view][GET] 게시글 해시태그 검색 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleHashtagSearchView_thenReturnsArticleHashtagSearchView() throws Exception {
// given
// when & then
mockMvc.perform(get("/articles/search-hashtag"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(view().name("articles/search-hashtag"))
;
}
private ArticleWithCommentsDto createArticleWithCommentDto() {
return ArticleWithCommentsDto.of(
1L,
createUserAccountDto(),
Set.of(),
"title",
"content",
"#java",
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby"
);
}
private UserAccountDto createUserAccountDto() {
return UserAccountDto.of(
1L,
"bobby",
"1234",
"bobby@email.com",
"bobby",
"memo",
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby"
);
}
}

View File

@@ -0,0 +1,38 @@
package com.example.board.controller;
import com.example.board.config.SecurityConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@DisplayName("View 컨트롤러 - 인증")
@Import(SecurityConfig.class)
@WebMvcTest
public class AuthControllerTest {
private final MockMvc mockMvc;
public AuthControllerTest(@Autowired MockMvc mockMvc) {
this.mockMvc = mockMvc;
}
@DisplayName("[view][GET] 로그인 페이지 - 정상 호출")
@Test
public void givenNothing_whenTryingToLogin_thenReturnsLoginView() throws Exception {
// given
// when & then
mockMvc.perform(get("/login"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
;
}
}

View File

@@ -0,0 +1,98 @@
package com.example.board.controller;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Disabled("Spring Data REST 통합테스트는 불필요하므로 제외")
@DisplayName("Data REST - API 테스트")
@AutoConfigureMockMvc
@Transactional
@SpringBootTest
public class DataRestTest {
private final MockMvc mockMvc;
public DataRestTest(@Autowired MockMvc mockMvc) {
this.mockMvc = mockMvc;
}
@DisplayName("[api] 게시글 리스트 조회")
@Test
void givenNothing_whenRequestingArticles_thenReturnsArticlesJsonResponse() throws Exception {
// given
// when & then
mockMvc.perform(get("/api/articles"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 게시글 단건 조회")
@Test
void givenNothing_whenRequestingArticle_thenReturnsArticleJsonResponse() throws Exception {
// given
// when & then
mockMvc.perform(get("/api/articles/1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 게시글 -> 댓글 리스트 조회")
@Test
void givenNothing_whenRequestingArticleCommentsFromArticle_thenReturnsArticleCommentsJsonResponse() throws Exception {
// given
// when & then
mockMvc.perform(get("/api/articles/1/articleComments"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 댓글 리스트 조회")
@Test
void givenNothing_whenRequestingArticleComments_thenReturnsArticleCommentsJsonResponse() throws Exception {
// given
// when & then
mockMvc.perform(get("/api/articleComments"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 댓글 단건 조회")
@Test
void givenNothing_whenRequestingArticleComment_thenReturnsArticleCommentJsonResponse() throws Exception {
// given
// when & then
mockMvc.perform(get("/api/articleComments/1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 회원 관련 API 는 일체 제공하지 않는다.")
@Test
void givenNothing_whenRequestingUserAccounts_thenThrowsException() throws Exception {
// Given
// When & Then
mockMvc.perform(get("/api/userAccounts")).andExpect(status().isNotFound());
mockMvc.perform(post("/api/userAccounts")).andExpect(status().isNotFound());
mockMvc.perform(put("/api/userAccounts")).andExpect(status().isNotFound());
mockMvc.perform(patch("/api/userAccounts")).andExpect(status().isNotFound());
mockMvc.perform(delete("/api/userAccounts")).andExpect(status().isNotFound());
mockMvc.perform(head("/api/userAccounts")).andExpect(status().isNotFound());
}
}

View File

@@ -0,0 +1,36 @@
package com.example.board.controller;
import com.example.board.config.SecurityConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@Import(SecurityConfig.class)
@WebMvcTest(MainController.class)
class MainControllerTest {
private final MockMvc mockMvc;
public MainControllerTest(@Autowired MockMvc mockMvc) {
this.mockMvc = mockMvc;
}
@Test
void givenNothing_whenRequestingRootPage_thenRedirectsToArticlesPage() throws Exception {
// given
// when & then
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("forward:/articles"))
.andExpect(forwardedUrl("/articles"))
.andDo(print())
;
}
}

View File

@@ -0,0 +1,97 @@
package com.example.board.repository;
import com.example.board.config.JpaConfig;
import com.example.board.domain.Article;
import com.example.board.domain.UserAccount;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("JPA 연결 테스트")
@Import(JpaConfig.class)
@DataJpaTest
class JpaRepositoryTest {
private final ArticleRepository articleRepository;
private final ArticleCommentRepository articleCommentRepository;
private final UserAccountRepository userAccountRepository;
public JpaRepositoryTest(
@Autowired ArticleRepository articleRepository,
@Autowired ArticleCommentRepository articleCommentRepository,
@Autowired UserAccountRepository userAccountRepository
) {
this.articleRepository = articleRepository;
this.articleCommentRepository = articleCommentRepository;
this.userAccountRepository = userAccountRepository;
}
@DisplayName("select 테스트")
@Test
void givenTestData_whenSelecting_thenWorksFine() {
// Given
// When
List<Article> articles = articleRepository.findAll();
// Then
assertThat(articles)
.isNotNull()
.hasSize(123);
}
@DisplayName("insert 테스트")
@Test
void givenTestData_whenInserting_thenWorksFine() {
// Given
long previousCount = articleRepository.count();
UserAccount userAccount =
userAccountRepository.save(UserAccount.of("bobby", "1234", null, null, null));
Article article =
articleRepository.save(Article.of(userAccount, "new article", "new content", "#spring"));
// When
articleRepository.save(article);
// Then
assertThat(articleRepository.count()).isEqualTo(previousCount + 1);
}
@DisplayName("update 테스트")
@Test
void givenTestData_whenUpdating_thenWorksFine() {
// Given
Article article = articleRepository.findById(1L).orElseThrow();
String updatedHashtag = "#springboot";
article.setHashtag(updatedHashtag);
// When
Article savedArticle = articleRepository.saveAndFlush(article);
// Then
assertThat(savedArticle).hasFieldOrPropertyWithValue("hashtag", updatedHashtag);
}
@DisplayName("delete 테스트")
@Test
void givenTestData_whenDeleting_thenWorksFine() {
// Given
Article article = articleRepository.findById(1L).orElseThrow();
long previousArticleCount = articleRepository.count();
long previousArticleCommentCount = articleCommentRepository.count();
int deletedCommentsSize = article.getArticleComments().size();
// When
articleRepository.delete(article);
// Then
assertThat(articleRepository.count()).isEqualTo(previousArticleCount - 1);
assertThat(articleCommentRepository.count()).isEqualTo(previousArticleCommentCount - deletedCommentsSize);
}
}

View File

@@ -0,0 +1,190 @@
package com.example.board.service;
import com.example.board.domain.Article;
import com.example.board.domain.ArticleComment;
import com.example.board.domain.UserAccount;
import com.example.board.dto.ArticleCommentDto;
import com.example.board.dto.UserAccountDto;
import com.example.board.repository.ArticleCommentRepository;
import com.example.board.repository.ArticleRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import javax.persistence.EntityNotFoundException;
import java.time.LocalDateTime;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.*;
@DisplayName("비즈니스 로직 - 댓글")
@ExtendWith(MockitoExtension.class)
class ArticleCommentServiceTest {
@InjectMocks
private ArticleCommentService sut;
@Mock
private ArticleRepository articleRepository;
@Mock
private ArticleCommentRepository articleCommentRepository;
@DisplayName("게시글 ID로 조회하면 해당하는 댓글 리스트를 반환한다.")
@Test
void givenArticleId_whenSearchingArticleComments_thenReturnsArticleComments() {
// given
Long articleId = 1L;
ArticleComment expected = createArticleComment("content");
given(articleCommentRepository.findByArticle_Id(articleId)).willReturn(List.of(expected));
// when
List<ArticleCommentDto> actual = sut.searchArticleComments(articleId);
// then
assertThat(actual)
.hasSize(1)
.first().hasFieldOrPropertyWithValue("content", expected.getContent());
then(articleCommentRepository).should().findByArticle_Id(articleId);
}
@DisplayName("댓글 정보를 입력하면, 댓글을 저장한다.")
@Test
void givenArticleCommentInfo_whenSavingArticleComment_thenSavesArticleComment() {
// Given
ArticleCommentDto dto = createArticleCommentDto("댓글");
given(articleRepository.getReferenceById(dto.articleId())).willReturn(createArticle());
// When
sut.saveArticleComment(dto);
// Then
then(articleRepository).should().getReferenceById(dto.articleId());
then(articleCommentRepository).should().save(any(ArticleComment.class));
}
@DisplayName("댓글 저장을 시도했는데 맞는 게시글이 없으면, 경고 로그를 찍고 아무것도 안 한다.")
@Test
void givenNonexistentArticle_whenSavingArticleComment_thenLogsSituationAndDoesNothing() {
// Given
ArticleCommentDto dto = createArticleCommentDto("댓글");
given(articleRepository.getReferenceById(dto.articleId())).willThrow(EntityNotFoundException.class);
// When
sut.saveArticleComment(dto);
// Then
then(articleRepository).should().getReferenceById(dto.articleId());
then(articleCommentRepository).shouldHaveNoInteractions();
}
@DisplayName("댓글 정보를 입력하면, 댓글을 수정한다.")
@Test
void givenArticleCommentInfo_whenUpdatingArticleComment_thenUpdatesArticleComment() {
// Given
String oldContent = "content";
String updatedContent = "댓글";
ArticleComment articleComment = createArticleComment(oldContent);
ArticleCommentDto dto = createArticleCommentDto(updatedContent);
given(articleCommentRepository.getReferenceById(dto.id())).willReturn(articleComment);
// When
sut.updateArticleComment(dto);
// Then
assertThat(articleComment.getContent())
.isNotEqualTo(oldContent)
.isEqualTo(updatedContent);
then(articleCommentRepository).should().getReferenceById(dto.id());
}
@DisplayName("없는 댓글 정보를 수정하려고 하면, 경고 로그를 찍고 아무 것도 안 한다.")
@Test
void givenNonexistentArticleComment_whenUpdatingArticleComment_thenLogsWarningAndDoesNothing() {
// Given
ArticleCommentDto dto = createArticleCommentDto("댓글");
given(articleCommentRepository.getReferenceById(dto.id())).willThrow(EntityNotFoundException.class);
// When
sut.updateArticleComment(dto);
// Then
then(articleCommentRepository).should().getReferenceById(dto.id());
}
@DisplayName("댓글 ID를 입력하면, 댓글을 삭제한다.")
@Test
void givenArticleCommentId_whenDeletingArticleComment_thenDeletesArticleComment() {
// Given
Long articleCommentId = 1L;
willDoNothing().given(articleCommentRepository).deleteById(articleCommentId);
// When
sut.deleteArticleComment(articleCommentId);
// Then
then(articleCommentRepository).should().deleteById(articleCommentId);
}
private ArticleCommentDto createArticleCommentDto(String content) {
return ArticleCommentDto.of(
1L,
1L,
createUserAccountDto(),
content,
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby"
);
}
private UserAccountDto createUserAccountDto() {
return UserAccountDto.of(
1L,
"bobby",
"password",
"bobby@mail.com",
"bobby",
"This is memo",
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby"
);
}
private ArticleComment createArticleComment(String content) {
return ArticleComment.of(
Article.of(createUserAccount(), "title", "content", "hashtag"),
createUserAccount(),
content
);
}
private UserAccount createUserAccount() {
return UserAccount.of(
"bobby",
"password",
"bobby@email.com",
"bobby",
null
);
}
private Article createArticle() {
return Article.of(
createUserAccount(),
"title",
"content",
"#java"
);
}
}

View File

@@ -0,0 +1,216 @@
package com.example.board.service;
import com.example.board.domain.Article;
import com.example.board.domain.UserAccount;
import com.example.board.domain.type.SearchType;
import com.example.board.dto.ArticleDto;
import com.example.board.dto.ArticleWithCommentsDto;
import com.example.board.dto.UserAccountDto;
import com.example.board.repository.ArticleRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import javax.persistence.EntityNotFoundException;
import java.time.LocalDateTime;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.BDDMockito.*;
@DisplayName("비즈니스 로직 - 게시글")
@ExtendWith(MockitoExtension.class)
class ArticleServiceTest {
@InjectMocks
private ArticleService sut;
@Mock
private ArticleRepository articleRepository;
@DisplayName("검색어 없이 게시글을 검색하면, 게시글 페이지를 반환한다.")
@Test
void givenNoSearchParameters_whenSearchingArticles_thenReturnsArticlePage() {
// given
Pageable pageable = Pageable.ofSize(20);
given(articleRepository.findAll(pageable)).willReturn(Page.empty());
// when
Page<ArticleDto> articles = sut.searchArticles(null, null, pageable);
// then
assertThat(articles).isEmpty();
then(articleRepository).should().findAll(pageable);
}
@DisplayName("검색어와 함께 게시글을 검색하면, 게시글 페이지를 반환한다.")
@Test
void givenSearchParameters_whenSearchingArticles_thenReturnsArticlePage() {
// Given
SearchType searchType = SearchType.TITLE;
String searchKeyword = "title";
Pageable pageable = Pageable.ofSize(20);
given(articleRepository.findByTitleContaining(searchKeyword, pageable)).willReturn(Page.empty());
// When
Page<ArticleDto> articles = sut.searchArticles(searchType, searchKeyword, pageable);
// Then
assertThat(articles).isEmpty();
then(articleRepository).should().findByTitleContaining(searchKeyword, pageable);
}
@DisplayName("게시글을 조회하면 게시글을 반환한다.")
@Test
void givenArticleId_whenSearchingArticle_thenReturnArticle() {
// given
Long articleId = 1L;
Article article = createArticle();
given(articleRepository.findById(articleId)).willReturn(Optional.of(article));
// When
ArticleWithCommentsDto dto = sut.getArticle(articleId);
// Then
assertThat(dto)
.hasFieldOrPropertyWithValue("title", article.getTitle())
.hasFieldOrPropertyWithValue("content", article.getContent())
.hasFieldOrPropertyWithValue("hashtag", article.getHashtag());
then(articleRepository).should().findById(articleId);
}
@DisplayName("없는 게시글을 조회하면, 예외를 던진다.")
@Test
void givenNonexistentArticleId_whenSearchingArticle_thenThrowsException() {
// Given
Long articleId = 0L;
given(articleRepository.findById(articleId)).willReturn(Optional.empty());
// When
Throwable t = catchThrowable(() -> sut.getArticle(articleId));
// Then
assertThat(t)
.isInstanceOf(EntityNotFoundException.class)
.hasMessage("게시글이 없습니다 - articleId: " + articleId);
then(articleRepository).should().findById(articleId);
}
@DisplayName("게시글 정보를 입력하면 게시글을 생성한다.")
@Test
void givenArticleInfo_whenSavingArticle_thenSavesArticle() {
// given
ArticleDto dto = createArticleDto();
given(articleRepository.save(any(Article.class))).willReturn(createArticle());
// when
sut.saveArticle(dto);
// then
then(articleRepository).should().save(any(Article.class));
}
@DisplayName("게시글의 수정 정보를 입력하면, 게시글을 수정한다.")
@Test
void givenArticleIdModifiedInfo_whenUpdatingArticle_thenUpdatesArticle() {
// given
Article article = createArticle();
ArticleDto dto = createArticleDto("새 타이틀", "새 내용", "#springboot");
given(articleRepository.getReferenceById(dto.id())).willReturn(article);
// when
sut.updateArticle(dto);
// then
assertThat(article)
.hasFieldOrPropertyWithValue("title", dto.title())
.hasFieldOrPropertyWithValue("content", dto.content())
.hasFieldOrPropertyWithValue("hashtag", dto.hashtag());
then(articleRepository).should().getReferenceById(dto.id());
}
@DisplayName("없는 게시글의 수정 정보를 입력하면, 경고 로그를 찍고 아무 것도 하지 않는다.")
@Test
void givenNonexistentArticleInfo_whenUpdatingArticle_thenLogsWarningAndDoesNothing() {
// Given
ArticleDto dto = createArticleDto("새 타이틀", "새 내용", "#springboot");
given(articleRepository.getReferenceById(dto.id())).willThrow(EntityNotFoundException.class);
// When
sut.updateArticle(dto);
// Then
then(articleRepository).should().getReferenceById(dto.id());
}
@DisplayName("게시글의 ID를 입력하면 게시글을 삭제한다.")
@Test
void givenArticleId_whenDeletingArticle_thenDeletesArticle() {
// given
Long articleId = 1L;
willDoNothing().given(articleRepository).deleteById(articleId);
// when
sut.deleteArticle(1L);
// then
then(articleRepository).should().deleteById(articleId);
}
private UserAccount createUserAccount() {
return UserAccount.of(
"bobby",
"password",
"bobby@email.com",
"bobby",
null
);
}
private Article createArticle() {
return Article.of(
createUserAccount(),
"title",
"content",
"#java"
);
}
private ArticleDto createArticleDto() {
return createArticleDto("title", "content", "#java");
}
private ArticleDto createArticleDto(String title, String content, String hashtag) {
return ArticleDto.of(1L,
createUserAccountDto(),
title,
content,
hashtag,
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby");
}
private UserAccountDto createUserAccountDto() {
return UserAccountDto.of(
1L,
"bobby",
"password",
"bobby@mail.com",
"bobby",
"This is memo",
LocalDateTime.now(),
"bobby",
LocalDateTime.now(),
"bobby"
);
}
}

View File

@@ -1,5 +1,7 @@
package com.example.effectivejava.chapter01.item03.staticfactory;
import java.util.function.Supplier;
// 코드 3-2 정적 팩터리 방식의 싱글턴 (24쪽)
public class Elvis implements Singer {
private static final Elvis INSTANCE = new Elvis();
@@ -15,6 +17,8 @@ public class Elvis implements Singer {
Elvis elvis = Elvis.getInstance();
elvis.leaveTheBuilding();
Supplier<Elvis> supplier = Elvis::getInstance;
System.out.println(Elvis.getInstance());
System.out.println(Elvis.getInstance());
}

View File

@@ -7,7 +7,6 @@ public class MetaElvis<T> {
private MetaElvis() { }
@SuppressWarnings("unchecked")
public static <E> MetaElvis<E> getInstance() { return (MetaElvis<E>) INSTANCE; }
public void say(T t) {

View File

@@ -0,0 +1,17 @@
package com.example.effectivejava.chapter01.item04;
public abstract class AbstractUtilityClass {
public AbstractUtilityClass() {
System.out.println("constructor");
}
public static String hello() {
return "hello";
}
public static void main(String[] args) {
String hello = AbstractUtilityClass.hello();
}
}

View File

@@ -0,0 +1,9 @@
package com.example.effectivejava.chapter01.item04;
public class DefaultUtilityClass extends AbstractUtilityClass {
public static void main(String[] args) {
DefaultUtilityClass utilityClass = new DefaultUtilityClass();
utilityClass.hello();
}
}

View File

@@ -0,0 +1,24 @@
package com.example.effectivejava.chapter01.item04;
public class UtilityClass {
/**
* 이 클래스는 인스턴스를 만들 수 없습니다.
*/
private UtilityClass() {
throw new AssertionError();
}
public static String hello() {
return "hello";
}
public static void main(String[] args) {
String hello = UtilityClass.hello();
UtilityClass utilityClass = new UtilityClass();
utilityClass.hello();
}
}

View File

@@ -0,0 +1,16 @@
package com.example.effectivejava.chapter01.item05;
import java.util.List;
public class DefaultDictionary implements Dictionary{
@Override
public boolean contains(String word) {
return false;
}
@Override
public List<String> closeWordsTo(String typo) {
return null;
}
}

View File

@@ -0,0 +1,10 @@
package com.example.effectivejava.chapter01.item05;
import java.util.List;
public interface Dictionary {
boolean contains(String word);
List<String> closeWordsTo(String typo);
}

View File

@@ -0,0 +1,15 @@
package com.example.effectivejava.chapter01.item05;
import java.util.List;
public class MockDictionary implements Dictionary{
@Override
public boolean contains(String word) {
return false;
}
@Override
public List<String> closeWordsTo(String typo) {
return null;
}
}

View File

@@ -0,0 +1,9 @@
package com.example.effectivejava.chapter01.item05.dependencyinjection;
import com.example.effectivejava.chapter01.item05.DefaultDictionary;
public class DictionaryFactory {
public static DefaultDictionary get() {
return new DefaultDictionary();
}
}

View File

@@ -0,0 +1,29 @@
package com.example.effectivejava.chapter01.item05.dependencyinjection;
import com.example.effectivejava.chapter01.item05.Dictionary;
import java.util.List;
import java.util.function.Supplier;
public class SpellChecker {
private final Dictionary dictionary;
public SpellChecker(Dictionary dictionary) {
this.dictionary = dictionary;
}
public SpellChecker(Supplier<Dictionary> dictionarySupplier) {
this.dictionary = dictionarySupplier.get();
}
public boolean isValid(String word) {
// TODO 여기 SpellChecker 코드
return dictionary.contains(word);
}
public List<String> suggestions(String typo) {
// TODO 여기 SpellChecker 코드
return dictionary.closeWordsTo(typo);
}
}

View File

@@ -0,0 +1,11 @@
package com.example.effectivejava.chapter01.item05.factorymethod;
import com.example.effectivejava.chapter01.item05.DefaultDictionary;
import com.example.effectivejava.chapter01.item05.Dictionary;
public class DefaultDictionaryFactory implements DictionaryFactory {
@Override
public Dictionary getDictionary() {
return new DefaultDictionary();
}
}

View File

@@ -0,0 +1,8 @@
package com.example.effectivejava.chapter01.item05.factorymethod;
import com.example.effectivejava.chapter01.item05.Dictionary;
public interface DictionaryFactory {
Dictionary getDictionary();
}

View File

@@ -0,0 +1,11 @@
package com.example.effectivejava.chapter01.item05.factorymethod;
import com.example.effectivejava.chapter01.item05.Dictionary;
import com.example.effectivejava.chapter01.item05.MockDictionary;
public class MockDictionaryFactory implements DictionaryFactory {
@Override
public Dictionary getDictionary() {
return new MockDictionary();
}
}

View File

@@ -0,0 +1,24 @@
package com.example.effectivejava.chapter01.item05.factorymethod;
import com.example.effectivejava.chapter01.item05.Dictionary;
import java.util.List;
public class SpellChecker {
private Dictionary dictionary;
public SpellChecker(DictionaryFactory dictionaryFactory) {
this.dictionary = dictionaryFactory.getDictionary();
}
public boolean isValid(String word) {
// TODO 여기 SpellChecker 코드
return dictionary.contains(word);
}
public List<String> suggestions(String typo) {
// TODO 여기 SpellChecker 코드
return dictionary.closeWordsTo(typo);
}
}

View File

@@ -0,0 +1,25 @@
package com.example.effectivejava.chapter01.item05.singleton;
import com.example.effectivejava.chapter01.item05.DefaultDictionary;
import com.example.effectivejava.chapter01.item05.Dictionary;
import java.util.List;
public class SpellChecker {
private final Dictionary dictionary = new DefaultDictionary();
private SpellChecker() {}
public static final SpellChecker INSTANCE = new SpellChecker();
public boolean isValid(String word) {
// TODO 여기 SpellChecker 코드
return dictionary.contains(word);
}
public List<String> suggestions(String typo) {
// TODO 여기 SpellChecker 코드
return dictionary.closeWordsTo(typo);
}
}

View File

@@ -0,0 +1,13 @@
package com.example.effectivejava.chapter01.item05.springioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
SpellChecker spellChecker = applicationContext.getBean(SpellChecker.class);
spellChecker.isValid("test");
}
}

View File

@@ -0,0 +1,21 @@
package com.example.effectivejava.chapter01.item05.springioc;
import com.example.effectivejava.chapter01.item05.Dictionary;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackageClasses = AppConfig.class)
public class AppConfig {
// @Bean
// public SpellChecker spellChecker(Dictionary dictionary) {
// return new SpellChecker(dictionary);
// }
//
// @Bean
// public Dictionary dictionary() {
// return new SpringDictionary();
// }
}

View File

@@ -0,0 +1,26 @@
package com.example.effectivejava.chapter01.item05.springioc;
import com.example.effectivejava.chapter01.item05.Dictionary;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class SpellChecker {
private Dictionary dictionary;
public SpellChecker(Dictionary dictionary) {
this.dictionary = dictionary;
}
public boolean isValid(String word) {
// TODO 여기 SpellChecker 코드
return dictionary.contains(word);
}
public List<String> suggestions(String typo) {
// TODO 여기 SpellChecker 코드
return dictionary.closeWordsTo(typo);
}
}

View File

@@ -0,0 +1,20 @@
package com.example.effectivejava.chapter01.item05.springioc;
import com.example.effectivejava.chapter01.item05.Dictionary;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class SpringDictionary implements Dictionary {
@Override
public boolean contains(String word) {
System.out.println("word = " + word);
return false;
}
@Override
public List<String> closeWordsTo(String typo) {
return null;
}
}

View File

@@ -0,0 +1,24 @@
package com.example.effectivejava.chapter01.item05.staticutils;
import com.example.effectivejava.chapter01.item05.DefaultDictionary;
import com.example.effectivejava.chapter01.item05.Dictionary;
import java.util.List;
public class SpellChecker {
private static final Dictionary dictionary = new DefaultDictionary();
private SpellChecker() {
}
public static boolean isValid(String word) {
// TODO 여기 SpellChecker 코드
return dictionary.contains(word);
}
public static List<String> suggestions(String typo) {
// TODO 여기 SpellChecker 코드
return dictionary.closeWordsTo(typo);
}
}

View File

@@ -0,0 +1,9 @@
package com.example.effectivejava.chapter01.item06;
public class Client {
public static void main(String[] args) {
Deprecation deprecation = new Deprecation();
Deprecation deprecation1 = new Deprecation("string");
}
}

View File

@@ -0,0 +1,18 @@
package com.example.effectivejava.chapter01.item06;
public class Deprecation {
/**
* @deprecated in favor of
* {@link #Deprecation(String)}
*/
@Deprecated(forRemoval = false, since = "1.2")
public Deprecation() {
}
private String name;
public Deprecation(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,18 @@
package com.example.effectivejava.chapter01.item06;
import java.util.regex.Pattern;
public class RegularExpression {
private static final Pattern SPLIT_PATTERN = Pattern.compile(",");
public static void main(String[] args) {
long start = System.nanoTime();
for (int j = 0; j < 10000; j++) {
String name = "keesun,whiteship";
name.split(",");
// SPLIT_PATTERN.split(name);
}
System.out.println(System.nanoTime() - start);
}
}

View File

@@ -0,0 +1,31 @@
package com.example.effectivejava.chapter01.item06;
import java.util.regex.Pattern;
// 값비싼 객체를 재사용해 성능을 개선한다. (32쪽)
public class RomanNumerals {
// 코드 6-1 성능을 훨씬 더 끌어올릴 수 있다!
static boolean isRomanNumeralSlow(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
// 코드 6-2 값비싼 객체를 재사용해 성능을 개선한다.
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeralFast(String s) {
return ROMAN.matcher(s).matches();
}
public static void main(String[] args) {
boolean result = false;
long start = System.nanoTime();
for (int j = 0; j < 100; j++) {
//TODO 성능 차이를 확인하려면 xxxSlow 메서드를 xxxFast 메서드로 바꿔 실행해보자.
result = isRomanNumeralSlow("MCMLXXVI");
}
long end = System.nanoTime();
System.out.println(end - start);
System.out.println(result);
}
}

View File

@@ -0,0 +1,18 @@
package com.example.effectivejava.chapter01.item06;
public class Strings {
public static void main(String[] args) {
String hello = "hello";
//TODO 이 방법은 권장하지 않습니다.
String hello2 = new String("hello");
String hello3 = "hello";
System.out.println(hello == hello2);
System.out.println(hello.equals(hello2));
System.out.println(hello == hello3);
System.out.println(hello.equals(hello3));
}
}

View File

@@ -0,0 +1,19 @@
package com.example.effectivejava.chapter01.item06;
public class Sum {
private static long sum() {
// TODO Long을 long으로 변경하여 실행해 보세요.
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}
public static void main(String[] args) {
long start = System.nanoTime();
long x = sum();
long end = System.nanoTime();
System.out.println((end - start) / 1_000_000. + " ms.");
System.out.println(x);
}
}

View File

@@ -0,0 +1,37 @@
package com.example.effectivejava.chapter01.item07.cache;
import java.time.LocalDateTime;
public class CacheKey {
private Integer value;
private LocalDateTime created;
public CacheKey(Integer value) {
this.value = value;
this.created = LocalDateTime.now();
}
@Override
public boolean equals(Object o) {
return this.value.equals(o);
}
@Override
public int hashCode() {
return this.value.hashCode();
}
public LocalDateTime getCreated() {
return created;
}
@Override
public String toString() {
return "CacheKey{" +
"value=" + value +
", created=" + created +
'}';
}
}

View File

@@ -0,0 +1,39 @@
package com.example.effectivejava.chapter01.item07.cache;
public class Post {
private Integer id;
private String title;
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public void finalize() {
System.out.println("gc called");
}
}

View File

@@ -0,0 +1,28 @@
package com.example.effectivejava.chapter01.item07.cache;
import java.util.Map;
import java.util.WeakHashMap;
public class PostRepository {
private Map<CacheKey, Post> cache;
public PostRepository() {
this.cache = new WeakHashMap<>();
}
public Post getPostById(CacheKey key) {
if (cache.containsKey(key)) {
return cache.get(key);
} else {
// TODO DB에서 읽어오거나 REST API를 통해 읽어올 수 있습니다.
Post post = new Post();
cache.put(key, post);
return post;
}
}
public Map<CacheKey, Post> getCache() {
return cache;
}
}

View File

@@ -0,0 +1,29 @@
package com.example.effectivejava.chapter01.item07.executor;
import java.util.concurrent.*;
public class ExecutorsExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(10);
Future<String> submit = service.submit(new Task());
System.out.println(Thread.currentThread() + " hello");
System.out.println(submit.get());
service.shutdown();
}
static class Task implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000L);
return Thread.currentThread() + " world";
}
}
}

View File

@@ -0,0 +1,27 @@
package com.example.effectivejava.chapter01.item07.listener;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ChatRoom {
private List<WeakReference<User>> users;
public ChatRoom() {
this.users = new ArrayList<>();
}
public void addUser(User user) {
this.users.add(new WeakReference<>(user));
}
public void sendMessage(String message) {
users.forEach(wr -> Objects.requireNonNull(wr.get()).receive(message));
}
public List<WeakReference<User>> getUsers() {
return users;
}
}

View File

@@ -0,0 +1,8 @@
package com.example.effectivejava.chapter01.item07.listener;
public class User {
public void receive(String message) {
System.out.println(message);
}
}

View File

@@ -0,0 +1,16 @@
package com.example.effectivejava.chapter01.item07.optional;
import java.util.Optional;
public class Channel {
private int numOfSubscribers;
public Optional<MemberShip> defaultMemberShip() {
if (this.numOfSubscribers < 2000) {
return Optional.empty();
} else {
return Optional.of(new MemberShip());
}
}
}

View File

@@ -0,0 +1,8 @@
package com.example.effectivejava.chapter01.item07.optional;
public class MemberShip {
public String hello() {
return "hello";
}
}

View File

@@ -0,0 +1,4 @@
package com.example.effectivejava.chapter01.item07.reference;
public class BigObject {
}

View File

@@ -0,0 +1,15 @@
package com.example.effectivejava.chapter01.item07.reference;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class BigObjectReference<BigObject> extends PhantomReference<BigObject> {
public BigObjectReference(BigObject referent, ReferenceQueue<? super BigObject> q) {
super(referent, q);
}
public void cleanUp() {
System.out.println("clean up");
}
}

View File

@@ -0,0 +1,26 @@
package com.example.effectivejava.chapter01.item07.reference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceExample {
public static void main(String[] args) throws InterruptedException {
BigObject strong = new BigObject();
ReferenceQueue<BigObject> rq = new ReferenceQueue<>();
BigObjectReference<BigObject> phantom = new BigObjectReference<>(strong, rq);
strong = null;
System.gc();
Thread.sleep(3000L);
// 사라지진 않고 큐에 들어갑니다.
System.out.println(phantom.isEnqueued());
Reference<? extends BigObject> reference = rq.poll();
BigObjectReference bigObjectCleaner = (BigObjectReference) reference;
bigObjectCleaner.cleanUp();
reference.clear();
}
}

View File

@@ -0,0 +1,18 @@
package com.example.effectivejava.chapter01.item07.reference;
import java.lang.ref.SoftReference;
public class SoftReferenceExample {
public static void main(String[] args) throws InterruptedException {
Object strong = new Object();
SoftReference<Object> soft = new SoftReference<>(strong);
strong = null;
System.gc();
Thread.sleep(3000L);
// 메모리가 충분해서.. 굳이 제거할 필요가 없어서 잘 안지워짐;;
System.out.println(soft.get());
}
}

View File

@@ -0,0 +1,17 @@
package com.example.effectivejava.chapter01.item07.reference;
import java.lang.ref.WeakReference;
public class WeakReferenceExample {
public static void main(String[] args) throws InterruptedException {
Object strong = new Object();
WeakReference<Object> weak = new WeakReference<>(strong);
strong = null;
System.gc();
Thread.sleep(3000L);
System.out.println(weak.get());
}
}

View File

@@ -0,0 +1,5 @@
package com.example.effectivejava.chapter01.item07.stack;
// (36쪽의 Stack 코드에서 던지는 예외)
public class EmptyStackException extends IllegalStateException {
}

View File

@@ -0,0 +1,52 @@
package com.example.effectivejava.chapter01.item07.stack;
import java.util.Arrays;
// 코드 7-1 메모리 누수가 일어나는 위치는 어디인가? (36쪽)
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
// public Object pop() {
// if (size == 0)
// throw new EmptyStackException();
// return elements[--size];
// }
/**
* 원소를 위한 공간을 적어도 하나 이상 확보한다.
* 배열 크기를 늘려야 할 때마다 대략 두 배씩 늘린다.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
// 코드 7-2 제대로 구현한 pop 메서드 (37쪽)
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // 다 쓴 참조 해제
return result;
}
public static void main(String[] args) {
Stack stack = new Stack();
for (String arg : args)
stack.push(arg);
while (true)
System.err.println(stack.pop());
}
}

View File

@@ -0,0 +1,11 @@
package com.example.effectivejava.chapter01.item08.autocloseable;
public class App {
public static void main(String[] args) {
try(AutoClosableIsGood good = new AutoClosableIsGood("")) {
// TODO 자원 반납 처리가 됨.
}
}
}

View File

@@ -0,0 +1,25 @@
package com.example.effectivejava.chapter01.item08.autocloseable;
import java.io.*;
public class AutoClosableIsGood implements AutoCloseable {
private BufferedReader reader;
public AutoClosableIsGood(String path) {
try {
this.reader = new BufferedReader(new FileReader(path));
} catch (FileNotFoundException e) {
throw new IllegalArgumentException(path);
}
}
@Override
public void close() {
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,27 @@
package com.example.effectivejava.chapter01.item08.cleaner;
import java.util.List;
public class BigObject {
private List<Object> resource;
public BigObject(List<Object> resource) {
this.resource = resource;
}
public static class ResourceCleaner implements Runnable {
private List<Object> resourceToClean;
public ResourceCleaner(List<Object> resourceToClean) {
this.resourceToClean = resourceToClean;
}
@Override
public void run() {
resourceToClean = null;
System.out.println("cleaned up.");
}
}
}

View File

@@ -0,0 +1,21 @@
package com.example.effectivejava.chapter01.item08.cleaner;
import java.lang.ref.Cleaner;
import java.util.ArrayList;
import java.util.List;
public class CleanerIsNotGood {
public static void main(String[] args) throws InterruptedException {
Cleaner cleaner = Cleaner.create();
List<Object> resourceToCleanUp = new ArrayList<>();
BigObject bigObject = new BigObject(resourceToCleanUp);
cleaner.register(bigObject, new BigObject.ResourceCleaner(resourceToCleanUp));
bigObject = null;
System.gc();
Thread.sleep(3000L);
}
}

View File

@@ -0,0 +1,10 @@
package com.example.effectivejava.chapter01.item08.cleaner_as_a_safeynet;
// cleaner 안전망을 갖춘 자원을 제대로 활용하는 클라이언트 (45쪽)
public class Adult {
public static void main(String[] args) {
try (Room myRoom = new Room(7)) {
System.out.println("안녕~");
}
}
}

View File

@@ -0,0 +1,38 @@
package com.example.effectivejava.chapter01.item08.cleaner_as_a_safeynet;
import java.lang.ref.Cleaner;
// 코드 8-1 cleaner를 안전망으로 활용하는 AutoCloseable 클래스 (44쪽)
public class Room implements AutoCloseable {
private static final Cleaner cleaner = Cleaner.create();
// 청소가 필요한 자원. 절대 Room을 참조해서는 안 된다!
private static class State implements Runnable {
int numJunkPiles; // Number of junk piles in this room
State(int numJunkPiles) {
this.numJunkPiles = numJunkPiles;
}
// close 메서드나 cleaner가 호출한다.
@Override public void run() {
System.out.println("Cleaning room");
numJunkPiles = 0;
}
}
// 방의 상태. cleanable과 공유한다.
private final State state;
// cleanable 객체. 수거 대상이 되면 방을 청소한다.
private final Cleaner.Cleanable cleanable;
public Room(int numJunkPiles) {
state = new State(numJunkPiles);
cleanable = cleaner.register(this, state);
}
@Override public void close() {
cleanable.clean();
}
}

View File

@@ -0,0 +1,14 @@
package com.example.effectivejava.chapter01.item08.cleaner_as_a_safeynet;
// cleaner 안전망을 갖춘 자원을 제대로 활용하지 못하는 클라이언트 (45쪽)
public class Teenager {
public static void main(String[] args) {
new Room(99);
System.out.println("Peace out");
// 다음 줄의 주석을 해제한 후 동작을 다시 확인해보자.
// 단, 가비지 컬렉러를 강제로 호출하는 이런 방식에 의존해서는 절대 안 된다!
System.gc();
}
}

View File

@@ -0,0 +1,30 @@
package com.example.effectivejava.chapter01.item08.finalizer;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
public class App {
/**
* 코드 참고 https://www.baeldung.com/java-finalize
*/
public static void main(String[] args) throws InterruptedException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
int i = 0;
while (true) {
i++;
new FinalizerIsBad();
if ((i % 1_000_000) == 0) {
Class<?> finalizerClass = Class.forName("java.lang.ref.Finalizer");
Field queueStaticField = finalizerClass.getDeclaredField("queue");
queueStaticField.setAccessible(true);
ReferenceQueue<Object> referenceQueue = (ReferenceQueue) queueStaticField.get(null);
Field queueLengthField = ReferenceQueue.class.getDeclaredField("queueLength");
queueLengthField.setAccessible(true);
long queueLength = (long) queueLengthField.get(referenceQueue);
System.out.format("There are %d references in the queue%n", queueLength);
}
}
}
}

View File

@@ -0,0 +1,9 @@
package com.example.effectivejava.chapter01.item08.finalizer;
public class FinalizerIsBad {
@Override
protected void finalize() throws Throwable {
System.out.print("");
}
}

Some files were not shown because too many files have changed in this diff Show More