first commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.example.project_it207_server;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ProjectIt207ServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ProjectIt207ServerApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "carts")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class Cart {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long cartId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
|
||||
@OneToMany(mappedBy = "cart", cascade = CascadeType.ALL)
|
||||
private List<CartItem> items;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Entity
|
||||
@Table(name = "cart_items")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
class CartItem {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long cartItemId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cart_id")
|
||||
private Cart cart;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "product_id")
|
||||
private Product product;
|
||||
|
||||
private int quantity;
|
||||
private BigDecimal price;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "categories")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class Category {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long categoryId;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String categoryName;
|
||||
|
||||
private String description;
|
||||
private String imageUrl;
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
private LocalDateTime updatedAt = LocalDateTime.now();
|
||||
|
||||
@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
|
||||
private List<Product> products;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "orders")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class Order {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long orderId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
private BigDecimal totalPrice;
|
||||
private String orderStatus = "PENDING";
|
||||
private String shippingAddress;
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
private LocalDateTime updatedAt = LocalDateTime.now();
|
||||
|
||||
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
|
||||
private List<OrderItem> orderItems;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Entity
|
||||
@Table(name = "order_items")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
class OrderItem {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long orderItemId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "order_id")
|
||||
private Order order;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "product_id")
|
||||
private Product product;
|
||||
|
||||
private int quantity;
|
||||
private BigDecimal price;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "products")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class Product {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long productId;
|
||||
|
||||
private String productName;
|
||||
private String description;
|
||||
private BigDecimal price;
|
||||
private int stockQuantity;
|
||||
private String imageUrl;
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
private LocalDateTime updatedAt = LocalDateTime.now();
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "category_id")
|
||||
private Category category;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "roles")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class Role {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long roleId;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String roleName;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.project_it207_server.model.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long userId;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String username;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String passwordHash;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String email;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String gender;
|
||||
private String phoneNumber;
|
||||
private String address;
|
||||
private String avatarUrl;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "role_id")
|
||||
private Role role;
|
||||
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
private LocalDateTime updatedAt = LocalDateTime.now();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.project_it207_server.redis;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
// Cấu hình serializer cho key (String)
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
|
||||
// Cấu hình serializer cho value (Object)
|
||||
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package com.example.project_it207_server.redis;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class RedisService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
// ===== VALUE OPERATIONS (String/Object) =====
|
||||
|
||||
/**
|
||||
* Lưu giá trị đơn giản với key
|
||||
*/
|
||||
public void setValue(String key, Object value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lưu giá trị với thời gian hết hạn
|
||||
*/
|
||||
public void setValueWithExpiry(String key, Object value, long timeout, TimeUnit timeUnit) {
|
||||
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy giá trị theo key
|
||||
*/
|
||||
public Object getValue(String key) {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chỉ set nếu key chưa tồn tại
|
||||
*/
|
||||
public Boolean setIfAbsent(String key, Object value) {
|
||||
return redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tăng giá trị số
|
||||
*/
|
||||
public Long increment(String key) {
|
||||
return redisTemplate.opsForValue().increment(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tăng giá trị số với delta
|
||||
*/
|
||||
public Long increment(String key, long delta) {
|
||||
return redisTemplate.opsForValue().increment(key, delta);
|
||||
}
|
||||
|
||||
// ===== HASH OPERATIONS =====
|
||||
|
||||
/**
|
||||
* Lưu field vào hash
|
||||
*/
|
||||
public void setHashField(String key, String field, Object value) {
|
||||
redisTemplate.opsForHash().put(key, field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy field từ hash
|
||||
*/
|
||||
public Object getHashField(String key, String field) {
|
||||
return redisTemplate.opsForHash().get(key, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy tất cả fields từ hash
|
||||
*/
|
||||
public Map<Object, Object> getAllHashFields(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kiểm tra field có tồn tại trong hash
|
||||
*/
|
||||
public Boolean hasHashField(String key, String field) {
|
||||
return redisTemplate.opsForHash().hasKey(key, field);
|
||||
}
|
||||
|
||||
// ===== LIST OPERATIONS =====
|
||||
|
||||
/**
|
||||
* Thêm vào đầu list
|
||||
*/
|
||||
public Long addToListLeft(String key, Object value) {
|
||||
return redisTemplate.opsForList().leftPush(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thêm vào cuối list
|
||||
*/
|
||||
public Long addToListRight(String key, Object value) {
|
||||
return redisTemplate.opsForList().rightPush(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy và xóa phần tử đầu list
|
||||
*/
|
||||
public Object popFromListLeft(String key) {
|
||||
return redisTemplate.opsForList().leftPop(key);
|
||||
}
|
||||
|
||||
public Object deleteItemListByIndex(String key, long index) {
|
||||
// Lấy phần tử tại index trước khi xóa
|
||||
Object itemToDelete = redisTemplate.opsForList().index(key, index);
|
||||
|
||||
if (itemToDelete != null) {
|
||||
// Xóa phần tử đầu tiên có giá trị bằng itemToDelete
|
||||
redisTemplate.opsForList().remove(key, 1, itemToDelete);
|
||||
return itemToDelete; // Trả về phần tử đã xóa
|
||||
}
|
||||
|
||||
return null; // Trả về null nếu không tìm thấy phần tử
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lấy range của list
|
||||
*/
|
||||
public List<Object> getListRange(String key, long start, long end) {
|
||||
return redisTemplate.opsForList().range(key, start, end);
|
||||
}
|
||||
|
||||
// ===== SET OPERATIONS =====
|
||||
|
||||
/**
|
||||
* Thêm vào set
|
||||
*/
|
||||
public Long addToSet(String key, Object... values) {
|
||||
return redisTemplate.opsForSet().add(key, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy tất cả members của set
|
||||
*/
|
||||
public Set<Object> getSetMembers(String key) {
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kiểm tra value có trong set
|
||||
*/
|
||||
public Boolean isSetMember(String key, Object value) {
|
||||
return redisTemplate.opsForSet().isMember(key, value);
|
||||
}
|
||||
|
||||
// ===== STRING REDIS TEMPLATE EXAMPLES =====
|
||||
|
||||
/**
|
||||
* Sử dụng StringRedisTemplate cho String operations
|
||||
*/
|
||||
public void setStringValue(String key, String value) {
|
||||
stringRedisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
public String getStringValue(String key) {
|
||||
return stringRedisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
public void setStringValueWithExpiry(String key, String value, Duration duration) {
|
||||
stringRedisTemplate.opsForValue().set(key, value, duration);
|
||||
}
|
||||
|
||||
// ===== UTILITY METHODS =====
|
||||
|
||||
/**
|
||||
* Kiểm tra key có tồn tại
|
||||
*/
|
||||
public Boolean hasKey(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Xóa key
|
||||
*/
|
||||
public Boolean deleteKey(String key) {
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set thời gian hết hạn cho key
|
||||
*/
|
||||
public Boolean expireKey(String key, long timeout, TimeUnit timeUnit) {
|
||||
return redisTemplate.expire(key, timeout, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lấy thời gian còn lại của key
|
||||
*/
|
||||
public Long getKeyExpiry(String key) {
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.example.project_it207_server.repository;
|
||||
|
||||
import com.example.project_it207_server.model.entity.Category;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CategoryRepository extends JpaRepository<Category, Long> {}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.example.project_it207_server.repository;
|
||||
|
||||
import com.example.project_it207_server.model.entity.Order;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface OrderRepository extends JpaRepository<Order, Long> {}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.example.project_it207_server.repository;
|
||||
|
||||
import com.example.project_it207_server.model.entity.Product;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.example.project_it207_server.repository;
|
||||
|
||||
import com.example.project_it207_server.model.entity.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findByUsername(String username);
|
||||
}
|
||||
16
src/main/resources/application.properties
Normal file
16
src/main/resources/application.properties
Normal file
@@ -0,0 +1,16 @@
|
||||
spring.application.name=project_it207_server
|
||||
|
||||
server.port=8080
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/project_it207?createDatabaseIfNotExist=true
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=true
|
||||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
jwt.secret-key=404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970
|
||||
jwt.expiration=86400000
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.project_it207_server;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class ProjectIt207ServerApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user