Commit 0d1a2f19 by Patryk Czarnik

Dodatkowe projekty, gdbymy nie zdążył pokazać na żywo

parent 5e4e1967
/target/
/.classpath
/.project
/.settings/
/*.iml
/.idea/
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.alx.kjava</groupId>
<artifactId>PC31-HibernateNaSerwerze</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package sklep.model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the customers database table.
*
*/
@Entity
@Table(name="customers")
@NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="customer_email")
private String customerEmail;
private String address;
private String city;
private String name;
@Column(name="phone_number")
private String phoneNumber;
@Column(name="postal_code")
private String postalCode;
//bi-directional many-to-one association to Order
@OneToMany(mappedBy="customer")
private List<Order> orders;
public Customer() {
}
public String getCustomerEmail() {
return this.customerEmail;
}
public void setCustomerEmail(String customerEmail) {
this.customerEmail = customerEmail;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return this.phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPostalCode() {
return this.postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public List<Order> getOrders() {
return this.orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public Order addOrder(Order order) {
getOrders().add(order);
order.setCustomer(this);
return order;
}
public Order removeOrder(Order order) {
getOrders().remove(order);
order.setCustomer(null);
return order;
}
}
\ No newline at end of file
package sklep.model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.sql.Timestamp;
import java.util.List;
/**
* The persistent class for the orders database table.
*
*/
@Entity
@Table(name="orders")
@NamedQuery(name="Order.findAll", query="SELECT o FROM Order o")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="order_id", insertable=false, updatable=false)
private Integer orderId;
@Temporal(TemporalType.DATE)
@Column(name="delivery_date")
private Date deliveryDate;
@Column(name="order_date")
private Timestamp orderDate;
@Temporal(TemporalType.DATE)
@Column(name="planned_delivery_date")
private Date plannedDeliveryDate;
private String status;
//bi-directional many-to-one association to OrderProduct
@OneToMany(mappedBy="order")
private List<OrderProduct> orderProducts;
//bi-directional many-to-one association to Customer
@ManyToOne
@JoinColumn(name="customer_email")
private Customer customer;
public Order() {
}
public Integer getOrderId() {
return this.orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public Date getDeliveryDate() {
return this.deliveryDate;
}
public void setDeliveryDate(Date deliveryDate) {
this.deliveryDate = deliveryDate;
}
public Timestamp getOrderDate() {
return this.orderDate;
}
public void setOrderDate(Timestamp orderDate) {
this.orderDate = orderDate;
}
public Date getPlannedDeliveryDate() {
return this.plannedDeliveryDate;
}
public void setPlannedDeliveryDate(Date plannedDeliveryDate) {
this.plannedDeliveryDate = plannedDeliveryDate;
}
public String getStatus() {
return this.status;
}
public void setStatus(String status) {
this.status = status;
}
public List<OrderProduct> getOrderProducts() {
return this.orderProducts;
}
public void setOrderProducts(List<OrderProduct> orderProducts) {
this.orderProducts = orderProducts;
}
public OrderProduct addOrderProduct(OrderProduct orderProduct) {
getOrderProducts().add(orderProduct);
orderProduct.setOrder(this);
return orderProduct;
}
public OrderProduct removeOrderProduct(OrderProduct orderProduct) {
getOrderProducts().remove(orderProduct);
orderProduct.setOrder(null);
return orderProduct;
}
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
\ No newline at end of file
package sklep.model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* The persistent class for the order_products database table.
*
*/
@Entity
@Table(name="order_products")
@NamedQuery(name="OrderProduct.findAll", query="SELECT o FROM OrderProduct o")
public class OrderProduct implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private OrderProductPK id;
@Column(name="actual_price")
private BigDecimal actualPrice;
@Column(name="actual_vat")
private BigDecimal actualVat;
private Integer quantity;
//bi-directional many-to-one association to Order
@ManyToOne
@JoinColumn(name="order_id", insertable=false, updatable=false)
private Order order;
//uni-directional many-to-one association to Product
@ManyToOne
@JoinColumn(name="product_id", insertable=false, updatable=false)
private Product product;
public OrderProduct() {
}
public OrderProductPK getId() {
return this.id;
}
public void setId(OrderProductPK id) {
this.id = id;
}
public BigDecimal getActualPrice() {
return this.actualPrice;
}
public void setActualPrice(BigDecimal actualPrice) {
this.actualPrice = actualPrice;
}
public BigDecimal getActualVat() {
return this.actualVat;
}
public void setActualVat(BigDecimal actualVat) {
this.actualVat = actualVat;
}
public Integer getQuantity() {
return this.quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public Order getOrder() {
return this.order;
}
public void setOrder(Order order) {
this.order = order;
}
public Product getProduct() {
return this.product;
}
public void setProduct(Product product) {
this.product = product;
}
}
\ No newline at end of file
package sklep.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The primary key class for the order_products database table.
*
*/
@Embeddable
public class OrderProductPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="order_id", insertable=false, updatable=false)
private Integer orderId;
@Column(name="product_id", insertable=false, updatable=false)
private Integer productId;
public OrderProductPK() {
}
public Integer getOrderId() {
return this.orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public Integer getProductId() {
return this.productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof OrderProductPK)) {
return false;
}
OrderProductPK castOther = (OrderProductPK)other;
return
this.orderId.equals(castOther.orderId)
&& this.productId.equals(castOther.productId);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.orderId.hashCode();
hash = hash * prime + this.productId.hashCode();
return hash;
}
}
\ No newline at end of file
package sklep.model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
/**
* The persistent class for the products database table.
*
*/
@Entity
@Table(name="products")
@NamedQuery(name="Product.findAll", query="SELECT p FROM Product p")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="product_id", insertable=false, updatable=false)
private Integer productId;
private String description;
private BigDecimal price;
@Column(name="product_name")
private String productName;
private BigDecimal vat;
public Product() {
}
public Integer getProductId() {
return this.productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public BigDecimal getPrice() {
return this.price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public BigDecimal getVat() {
return this.vat;
}
public void setVat(BigDecimal vat) {
this.vat = vat;
}
}
\ No newline at end of file
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sklep.model.Product;
// http://localhost:8080/PC29-HibernateNaSerwerze-1.0/Lista0
@WebServlet("/lista0")
public class Lista0 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
// W tej wersji obiekty JPA (emf i em) otwieram w sposób ogólny, tak jakby to była zwykła aplikacja.
// Nie zakładam, że jestem na serwerze.
EntityManagerFactory emf = null;
EntityManager em = null;
try {
emf = Persistence.createEntityManagerFactory("sklep");
em = emf.createEntityManager();
out.println("Mam połączenie. em = " + em);
TypedQuery<Product> query = em.createNamedQuery("Product.findAll", Product.class);
List<Product> products = query.getResultList();
out.println("Odczytano " + products.size() + " produktów:");
for (Product product : products) {
out.println(" * " + product.getProductName() + " za " + product.getPrice());
}
} catch(Exception e) {
out.println("Katastrofa " + e);
e.printStackTrace(out);
} finally {
if(em != null) em.close();
if(emf != null) emf.close();
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sklep.model.Product;
// Wersja z ręcznym uzyskaniem dostępu do `persistence` - poprzez fabrykę, a nie wstrzykiwanie zależności.
// To jest napisane niemal tak, jak "zwykły program z mainem".
// To serwer zapewnia implementację JPA - my nie dodajemy jej do pom.xml (dodajemy tylko javaee-web-api)
// WildFly użyje Hibernate, a Glassfish użyje Eclipse Link.
// Wersja zadziała także przy konfiguracji połączenia "RESOURCE_LOCAL" z parametrami połączenia podanymi w persistence.xml
@WebServlet("/lista1")
public class Lista1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
EntityManagerFactory emf = null;
EntityManager em = null;
try {
emf = Persistence.createEntityManagerFactory("sklep");
em = emf.createEntityManager();
TypedQuery<Product> query = em.createNamedQuery("Product.findAll", Product.class);
List<Product> products = query.getResultList();
out.println("Odczytano " + products.size() + " rekordów:");
for (Product product : products) {
out.println(product.getProductName() + " " + product.getPrice());
}
} catch(Exception e) {
out.println("Wyjątek: " + e);
} finally {
if(em != null) em.close();
if(emf != null) emf.close();
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sklep.model.Product;
// Wersja ze wstrzykiwaniem EntityManagerFactory za pomocą adnotacji @PersistenceUnit.
// Jeśli w aplikacji jest tylko jeden persistence unit, to nazwy można nie podawać, ale ja wolę zawsze podać.
// Ta wersja jest odpowiednia także dla konfiguracji opartej o RESOURCE_LOCAL
@WebServlet("/lista2")
public class Lista2 extends HttpServlet {
private static final long serialVersionUID = 1L;
@PersistenceUnit(unitName="sklep")
private EntityManagerFactory emf;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
EntityManager em = null;
try {
em = emf.createEntityManager();
TypedQuery<Product> query = em.createNamedQuery("Product.findAll", Product.class);
List<Product> products = query.getResultList();
out.println("Odczytano " + products.size() + " rekordów:");
for (Product product : products) {
out.println(product.getProductName() + " " + product.getPrice());
}
} catch(Exception e) {
out.println("Wyjątek: " + e + "\n");
e.printStackTrace(out);
} finally {
if(em != null) em.close();
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sklep.model.Product;
// Wersja ze wstrzykiwaniem EntityManager (a nie fabryki) za pomocą adnotacji @PersistenceContext.
// Jeśli w aplikacji jest tylko jeden persistence unit, to nazwy można nie podawać, ale ja wolę zawsze podać.
// Ta wersja jest odpowiednia dla konfiguracji opartej o JTA
@WebServlet("/lista3")
public class Lista3 extends HttpServlet {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName="sklep")
private EntityManager em;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
TypedQuery<Product> query = em.createNamedQuery("Product.findAll", Product.class);
List<Product> products = query.getResultList();
out.println("Odczytano " + products.size() + " rekordów:");
for (Product product : products) {
out.println(product.getProductName() + " " + product.getPrice());
}
} catch(Exception e) {
out.println("Wyjątek: " + e + "\n");
e.printStackTrace(out);
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/sql1")
public class Sql1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
final String sql = "SELECT * FROM products";
try (Connection c = DriverManager.getConnection("jdbc:postgresql://localhost/sklep", "kurs", "abc123")) {
out.println("Connection połączone: " + c);
try (PreparedStatement stmt = c.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("product_id");
String productName = rs.getString("product_name");
BigDecimal price = rs.getBigDecimal("price");
String description = rs.getString("description");
out.printf("\n * Produkt nr %d: %s w cenie %s (%s)\n", id, productName, price, description);
}
}
}
}
} catch (SQLException e) {
e.printStackTrace(out);
} catch (Exception e) {
e.printStackTrace(out);
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
@WebServlet("/sql2")
public class Sql2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
// Połączenie z bazą (jako DataSource) pobieramy z rejestru serwera (technologia JNDI - zasoby zarządzane przez serwer Java EE)
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/SklepDS");
out.println("DataSource znaleziony: " + ds);
final String sql = "SELECT * FROM products";
try (Connection c = ds.getConnection()) {
try (PreparedStatement stmt = c.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("product_id");
String productName = rs.getString("product_name");
BigDecimal price = rs.getBigDecimal("price");
String description = rs.getString("description");
out.printf("\n * Produkt nr %d: %s w cenie %s (%s)\n", id, productName, price, description);
}
}
}
}
} catch (SQLException e) {
e.printStackTrace(out);
} catch (NamingException e) {
e.printStackTrace(out);
} catch (Exception e) {
e.printStackTrace(out);
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
@WebServlet("/sql3")
public class Sql3 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Resource(lookup="java:/SklepDS")
private DataSource ds;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("DataSource wstrzyknięty: " + ds);
final String sql = "SELECT * FROM products";
try (Connection c = ds.getConnection()) {
try (PreparedStatement stmt = c.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("product_id");
String productName = rs.getString("product_name");
BigDecimal price = rs.getBigDecimal("price");
String description = rs.getString("description");
out.printf("\n * Produkt nr %d: %s w cenie %s (%s)\n", id, productName, price, description);
}
}
}
}
} catch (SQLException e) {
e.printStackTrace(out);
} catch (Exception e) {
e.printStackTrace(out);
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sklep.model.Product;
@WebServlet("/zmiana2")
public class Zmiana2 extends HttpServlet {
private static final long serialVersionUID = 1L;
@PersistenceUnit(unitName="sklep")
private EntityManagerFactory emf;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if(request.getParameter("id") == null) {
out.println("Trzeba podać id produktu");
return;
}
Integer id = Integer.valueOf(request.getParameter("id"));
BigDecimal podwyzka = null;
if(request.getParameter("podwyzka") != null) {
podwyzka = new BigDecimal(request.getParameter("podwyzka"));
}
EntityManager em = null;
try {
em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Product product = em.find(Product.class, id);
if(product == null) {
out.println("Nie znaleziono produktu o numerze " + id);
return;
}
out.println(product.getProductName() + " " + product.getPrice());
if(podwyzka != null) {
product.setPrice(product.getPrice().add(podwyzka));
}
out.println("Po zmianie:");
out.println(product.getProductName() + " " + product.getPrice());
transaction.commit();
} catch (SecurityException | IllegalStateException e) {
throw new ServletException("wielka bieda", e);
} finally {
if(em != null) {
em.close();
}
}
}
}
package sklep.serwlety;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
import sklep.model.Product;
@WebServlet("/zmiana3")
public class Zmiana3 extends HttpServlet {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName="sklep")
private EntityManager em;
@Resource
private UserTransaction transaction; // konwencja nazw: utx
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if(request.getParameter("id") == null) {
out.println("Trzeba podać id produktu");
return;
}
Integer id = Integer.valueOf(request.getParameter("id"));
BigDecimal podwyzka = null;
if(request.getParameter("podwyzka") != null) {
podwyzka = new BigDecimal(request.getParameter("podwyzka"));
}
try {
transaction.begin();
Product product = em.find(Product.class, id);
if(product == null) {
out.println("Nie znaleziono produktu o numerze " + id);
return;
}
out.println(product.getProductName() + " " + product.getPrice());
if(podwyzka != null) {
product.setPrice(product.getPrice().add(podwyzka));
}
out.println("Po zmianie:");
out.println(product.getProductName() + " " + product.getPrice());
transaction.commit();
// } catch (SecurityException | IllegalStateException | RollbackException | HeuristicMixedException | HeuristicRollbackException | SystemException | NotSupportedException e) {
} catch (Exception e) {
throw new ServletException("wielka bieda", e);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="sklep" transaction-type="JTA">
<jta-data-source>java:/SklepDS</jta-data-source>
<class>sklep.model.Customer</class>
<class>sklep.model.OrderProduct</class>
<class>sklep.model.OrderProductPK</class>
<class>sklep.model.Order</class>
<class>sklep.model.Product</class>
<properties>
<property name="hibernate.show_sql" value="true"/> <!-- pokazywanie zapytań SQL -->
</properties>
</persistence-unit>
</persistence>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hibernate na serwerze</title>
</head>
<body>
<h1>Hibernate na serwerze</h1>
<h2>Zapytania SQL</h2>
<ul>
<li><a href="sql1">sql1</a> - normalne <code>getConnection</code> - nie zadziała bez sterownika</li>
<li><a href="sql2">sql2</a> - DataSource za pomocą <code>ctx.lookup</code></li>
<li><a href="sql3">sql3</a> - wstrzykiwanie DataSource</li>
</ul>
<h2>Zapytania JPA/Hibernate</h2>
<ul>
<li><a href="lista0">lista0</a> - wersja bez konfiguracji serwera, później zmieniona na użycie data source typu resource/local</li>
<li><a href="lista1">lista1</a> - stara wersja odstawowa</li>
<li><a href="lista2">lista2</a> - wersja ze wstrzykiwaniem EntityManagerFactory, działająca dla datasource typu resource/local</li>
<li><a href="lista3">lista3</a> - wersja ze wstrzykiwaniem EntityManager, działająca dla datasource typu JTA (wymaga zmiany konfiguracji)</li>
</ul>
<h2>Modyfikacja danych JPA/Hibernate</h2>
<p>(podwyżka ceny pralki o 500)</p>
<ul>
<li><a href="zmiana2?id=1&amp;podwyzka=500">zmiana2</a> - wersja dla datasource typu resource/local</li>
<li><a href="zmiana3?id=1&amp;podwyzka=500">zmiana3</a> - wersja dla datasource typu JTA (wymaga zmiany konfiguracji)</li>
</ul>
</body>
</html>
\ No newline at end of file
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'pl.alx.kjava'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/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/HEAD/platforms/jvm/plugins-application/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
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# 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
if ! command -v java >/dev/null 2>&1
then
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
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
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
# 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"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
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" "$@"
@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=.
@rem This is normally unused
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. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
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
rootProject.name = 'PC36-SpringTechnicznie'
package com.example.demo;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/")
public String root() {
return "index.html";
}
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("txt", "Hello world!");
model.addAttribute("time", LocalTime.now());
return "hello.html";
}
@RequestMapping("/ping")
public String ping(HttpServletRequest request, Model model) {
// Do modelu można też dodać słownik / mapę.
// Odczyt wartości wygląda później np. tak ${clientInfo.userAgent}
String ip = request.getRemoteAddr();
System.out.println("Zapytanie z adresu " + ip);
model.addAttribute("clientInfo", Map.of(
"userAgent", request.getHeader("User-Agent"),
"ip", ip,
"data", LocalDateTime.now()
));
return "ping.html";
}
}
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Pc36SpringTechnicznieApplication {
public static void main(String[] args) {
SpringApplication.run(Pc36SpringTechnicznieApplication.class, args);
}
}
package com.example.demo.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.example.demo.model.Employee;
@Controller
public class Controller0 {
@Autowired
private Repository0_Memory repository;
@GetMapping("/emps0")
public String showExampleEmployee(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
}
package com.example.demo.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.model.Employee;
@Controller
@RequestMapping("/emps1")
public class Controller1_EM {
/* W tej wersji Controller bezpośrednio korzysta z technologii JPA/Hibernate.
* Ułatwieniem jest to, że Spring automatycznie "wstryknie" nam obiekt EntityManager.
*/
@Autowired
private EntityManager em;
@GetMapping
public String showAll(Model model) {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = em.find(Employee.class, employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
}
package com.example.demo.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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;
import com.example.demo.model.Employee;
@Controller
@RequestMapping("/emps2")
public class Controller2 {
@Autowired
private Repository2 repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = repository.findOne(employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
}
package com.example.demo.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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;
import com.example.demo.model.Employee;
@Controller
@RequestMapping("/emps3")
public class Controller3 {
/* Aby bezpośrednio w Controllerze nie używać kodów dot. Hibernate, SQL itd...
* wydzielam operacje bazodanowe do oddzielnej klasy, opisanej jako Repository
* i wstrzykuję referencję do repozytorium tutaj w controllerze.
* W doatku robię to porzez interfejs (zgodne z najlepszymi praktykami Springa),
* aby ułatwić podmianę implementacji na inną.
*/
@Autowired
private Repository3_Interface repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = repository.findOne(employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
}
package com.example.demo.data;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.model.Employee;
@Controller
@RequestMapping("/emps4")
public class Controller4 {
@Autowired
private Repository4 repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Optional<Employee> emp = repository.findById(employeeId);
List<Employee> emps;
if (emp.isPresent()) {
emps = List.of(emp.get());
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
}
package com.example.demo.data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.demo.model.Employee;
@Controller
@RequestMapping("/emps5")
public class Controller5 {
@Autowired
private Repository5 repository;
@GetMapping("/all")
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/by_id/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Optional<Employee> emp = repository.findById(employeeId);
List<Employee> emps;
if (emp.isPresent()) {
emps = List.of(emp.get());
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_job/IT_PROG
@GetMapping("/by_job/{job}")
public String getEmployeesByJobId(Model model,
@PathVariable("job") String jobId) {
List<Employee> emps = repository.findByJob_JobId(jobId);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_city/Oxford
@GetMapping("/by_city/{city}")
public String getEmployeesByCity(Model model,
@PathVariable("city") String city) {
List<Employee> emps = repository.findByDepartment_Location_City(city);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_salary?min=5000&max=10000
@GetMapping("/by_salary")
public String getEmployeesBySalary(Model model,
@RequestParam(name="min", defaultValue="0") BigDecimal min,
@RequestParam(name="max", defaultValue="1000000000") BigDecimal max) {
List<Employee> employees = repository.findBySalary(min, max);
model.addAttribute("emps", employees);
return "employees.html";
}
@GetMapping("/by_year/{year}")
public String getEmployeesByYear(Model model,
@PathVariable("year") int year) {
List<String> names = repository.namesByYear(year);
model.addAttribute("names", names);
return "names.html";
}
@GetMapping("/zara")
public String zarabiajacy(Model model,
@RequestParam("id") int id) {
List<Employee> emps = repository.zarabiajacyWiecejNiz(id);
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/szef/{id}")
@ResponseBody
public String szef(@PathVariable("id") Integer idPracownika) {
return repository.nazwiskoSzefa(idPracownika);
}
@GetMapping("/save/{id}")
public String modify(Model model,
@PathVariable("id") Integer idPracownika,
@RequestParam(value="salary", required=false) BigDecimal newSalary,
@RequestParam(value="first_name", required=false) String newFirstName,
@RequestParam(value="last_name", required=false) String newLastName) {
Optional<Employee> found = repository.findById(idPracownika);
List<Employee> emps;
if(found.isPresent()) {
Employee emp = found.get();
if(newSalary != null)
emp.setSalary(newSalary);
if(newFirstName != null)
emp.setFirstName(newFirstName);
if(newLastName != null)
emp.setLastName(newLastName);
repository.save(emp);
emps = List.of(emp);
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/move/{id}")
@ResponseBody
public String modify(Model model,
@PathVariable("id") Integer idPracownika,
@RequestParam(value="dep", required=false) int newDep,
@RequestParam(value="job", required=false) String newJob) {
repository.moveEmployee(idPracownika, newDep, newJob);
return "Przeniesiono";
}
}
package com.example.demo.data;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Department;
import com.example.demo.model.Employee;
import com.example.demo.model.Job;
import com.example.demo.model.Location;
/* Klasa pełniąca rolę repozytoium, czyli dostraczanie danych,
* ale zaimplementowana bez bazy danych - po prostu zwraca przykładowe obiekty.
*/
@Repository
public class Repository0_Memory {
public List<Employee> findAll() {
Employee emp = exampleEmployee1();
return List.of(emp);
}
private Employee exampleEmployee1() {
Employee emp = new Employee();
emp.setFirstName("Jan");
emp.setLastName("Kowalski");
emp.setSalary(BigDecimal.valueOf(12345));
emp.setJob(exampleJob());
emp.setDepartment(exampleDepartment());
return emp;
}
private Department exampleDepartment() {
Location loc = new Location();
loc.setCity("Warszawa");
Department dep = new Department();
dep.setDepartmentName("Szkolenia");
dep.setLocation(loc);
return dep;
}
private Job exampleJob() {
Job job = new Job();
job.setJobTitle("Trainer");
return job;
}
}
package com.example.demo.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Employee;
@Repository
public class Repository2 {
@Autowired
private EntityManager em;
public List<Employee> findAll() {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
return emps;
}
public Employee findOne(int employeeId) {
return em.find(Employee.class, employeeId);
}
public List<Employee> findByLastName(String lastName) {
TypedQuery<Employee> query = em.createQuery(
"SELECT emp FROM Employee emp WHERE emp.lastName = :name", Employee.class);
query.setParameter("name", lastName);
List<Employee> emps = query.getResultList();
return emps;
}
}
package com.example.demo.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Employee;
@Repository
public class Repository3_Impl implements Repository3_Interface {
@Autowired
private EntityManager em;
@Override
public List<Employee> findAll() {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
return emps;
}
@Override
public Employee findOne(int employeeId) {
return em.find(Employee.class, employeeId);
}
@Override
public List<Employee> findByLastName(String lastName) {
TypedQuery<Employee> query = em.createQuery(
"SELECT emp FROM Employee emp WHERE emp.lastName = :name", Employee.class);
query.setParameter("name", lastName);
List<Employee> emps = query.getResultList();
return emps;
}
}
package com.example.demo.data;
import java.util.List;
import com.example.demo.model.Employee;
public interface Repository3_Interface {
List<Employee> findAll();
Employee findOne(int employeeId);
List<Employee> findByLastName(String lastName);
}
\ No newline at end of file
package com.example.demo.data;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Employee;
public interface Repository4 extends JpaRepository<Employee, Integer> {
// Spring sam tworzy instancję tego interfejsu, która zawiera implementację wszystkich standardowych metod
}
package com.example.demo.data;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.example.demo.model.Employee;
public interface Repository5 extends JpaRepository<Employee, Integer> {
List<Employee> findByLastName(String name);
List<Employee> findByLastNameContainingIgnoringCase(String name);
List<Employee> findByJob_JobId(String jobId);
// employee.getDepartment().getLocation().getCity()
// ale w zapytaniu zostanie to zamienione na SQL, który JOIN-em dołącza tabele departments i locations i w WHERE sprawdza city
List<Employee> findByDepartment_Location_City(String city);
// Zapytanie w składni JPQL
@Query("SELECT emp FROM Employee emp WHERE emp.salary BETWEEN :min AND :max ORDER BY emp.salary")
List<Employee> findBySalary(BigDecimal min, BigDecimal max);
@Query(nativeQuery=true,
value="""
SELECT first_name || ' ' || last_name
FROM employees
WHERE extract(year FROM hire_date) = :year
ORDER BY last_name
""")
List<String> namesByYear(int year);
// W ramach takiego interfejsu można też pisać metody z własną implementacją.
// Tu przykład już nie bazodanowy...
default List<Integer> losowe(int limit, int ilosc) {
return ThreadLocalRandom.current().ints(ilosc, 0, limit).boxed().collect(Collectors.toList());
}
// podobno tak wygląda wywołanie procedury składowanej, ale nam nie działa
@Query(nativeQuery=true, value="CALL przenies_pracownika(:idPracownika, :newDep, :newJob)")
void moveEmployee(Integer idPracownika, int newDep, String newJob);
@Query(nativeQuery=true, value="SELECT zarabiajacy_wiecej_niz(:id)")
List<Employee> zarabiajacyWiecejNiz(int id);
@Query(nativeQuery=true, value="SELECT nazwisko_szefa(:idPracownika)")
String nazwiskoSzefa(Integer idPracownika);
}
package com.example.demo.licznik;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
@Controller
public class AController1 {
@GetMapping("/test0")
public String test0() {
return "licznik.html";
}
@GetMapping("/test1")
public String test1(Model model) {
model.addAttribute("licznik", "Ala ma kota, a nie żaden licznik");
return "licznik.html";
}
@GetMapping("/test2")
public String test2(Model model, Licznik licznik) {
// Nawet gdy sami nie dodamy obiektu do modelu, to Spring i tak to zrobi
// model.addAttribute("licznik", licznik);
return "licznik.html";
}
@GetMapping("/test3")
public String test3(@ModelAttribute Licznik licznik) {
// Ta adnotacja mówi jednoznacznie, że ten parametr jest elementem modelu
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
@Controller
public class AController4 {
@ModelAttribute
public Licznik getLicznik() {
// Gdy w klasie istynieje taka metoda oznaczona @ModelAttribute, to ona zostanie użyta do utworzenia obiektu.
// Jeśli nie ma takiej metody (jak w Controller1), to konstruktor domyślny.
return new Licznik("ModelAttribute z metody", 400);
}
@GetMapping("/test4")
public String test4(@ModelAttribute Licznik licznik) {
return "licznik.html";
}
@GetMapping("/test4a")
public String test4a(Licznik licznik) {
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@SessionAttributes({"licznik"})
public class AController5 {
// W tej wersji atrybut modelu żyje w zakresie sesji.
@ModelAttribute
public Licznik getLicznik() {
return new Licznik("v5 z metody", 500);
}
@GetMapping("/test5")
public String test5(@ModelAttribute Licznik licznik) {
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class AController6 {
@Autowired
private LicznikComponent6 licznikComponent6;
@GetMapping("/test6")
public String test6(Model model) {
model.addAttribute("licznik", licznikComponent6.getLicznik());
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class AController7 {
@Autowired
private LicznikComponent7 licznikComponent7;
@GetMapping("/test7")
public String test7(Model model) {
model.addAttribute("licznik", licznikComponent7.getLicznik());
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class AController8 {
@Autowired
private LicznikBean8 licznikBean8;
@GetMapping("/test8")
public String test8(Model model) {
model.addAttribute("licznik", licznikBean8.getLicznik());
return "licznik.html";
}
}
package com.example.demo.licznik;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Configuration8 {
// Adnotacja @Bean jest używana na poziomie metody.
// Wynik wywołania tej metody zostanie zapamiętany przez Springa i będzie traktowany jak "bean",
// czyli zostanie wstrzyknięty tam, gdzie będzie go ktoś potrzebował.
// Taka metoda musi być umieszczona w klasie, którą "przeczyta" Spring i wykona takie metody.
// Najczęściej stosuje się klasy oznaczone @Configuration
@Bean
public LicznikBean8 generuj() {
LicznikBean8 wynik = new LicznikBean8();
wynik.setLicznik(new Licznik("bean z konfiguracji", 800));
return wynik;
}
}
package com.example.demo.licznik;
public class Licznik {
private String napis;
private int value;
public Licznik(String napis, int value) {
this.napis = napis;
this.value = value;
}
public Licznik() {
this("default", 0);
}
public synchronized String getNapis() {
return napis;
}
public synchronized void setNapis(String napis) {
this.napis = napis;
}
public synchronized int getValue() {
return ++value;
}
@Override
public String toString() {
return "Licznik [napis: " + getNapis() + ", value: " + getValue() + "]";
}
}
package com.example.demo.licznik;
public class LicznikBean8 {
private Licznik licznik;
public Licznik getLicznik() {
return licznik;
}
public void setLicznik(Licznik licznik) {
this.licznik = licznik;
}
}
package com.example.demo.licznik;
import org.springframework.stereotype.Component;
@Component // albo @Service, @Repository
public class LicznikComponent6 {
private Licznik licznik = new Licznik();
public Licznik getLicznik() {
return licznik;
}
public void setLicznik(Licznik licznik) {
this.licznik = licznik;
}
}
package com.example.demo.licznik;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component
@Scope(scopeName="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class LicznikComponent7 {
private Licznik licznik = new Licznik();
public Licznik getLicznik() {
return licznik;
}
public void setLicznik(Licznik licznik) {
this.licznik = licznik;
}
}
package com.example.demo.model;
import java.io.Serializable;
import jakarta.persistence.*;
/**
* The persistent class for the countries database table.
*
*/
@Entity
@Table(name="countries")
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c")
public class Country implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="country_id")
private String countryId;
@Column(name="country_name")
private String countryName;
//bi-directional many-to-one association to Region
@ManyToOne
@JoinColumn(name="region_id")
private Region region;
public Country() {
}
public String getCountryId() {
return this.countryId;
}
public void setCountryId(String countryId) {
this.countryId = countryId;
}
public String getCountryName() {
return this.countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public Region getRegion() {
return this.region;
}
public void setRegion(Region region) {
this.region = region;
}
}
\ No newline at end of file
package com.example.demo.model;
import java.io.Serializable;
import java.util.List;
import jakarta.persistence.*;
/**
* The persistent class for the departments database table.
*
*/
@Entity
@Table(name="departments")
@NamedQuery(name="Department.findAll", query="SELECT d FROM Department d")
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name="DEPARTMENTS_DEPARTMENTID_GENERATOR", sequenceName="DEPARTMENTS_SEQ", allocationSize=10)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DEPARTMENTS_DEPARTMENTID_GENERATOR")
@Column(name="department_id")
private Integer departmentId;
@Column(name="department_name")
private String departmentName;
@Column(name="manager_id")
private Integer managerId;
//uni-directional many-to-one association to Location
@ManyToOne
@JoinColumn(name="location_id")
private Location location;
//bi-directional many-to-one association to Employee
@OneToMany(mappedBy="department")
private List<Employee> employees;
public Department() {
}
public Integer getDepartmentId() {
return this.departmentId;
}
public void setDepartmentId(Integer departmentId) {
this.departmentId = departmentId;
}
public String getDepartmentName() {
return this.departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public Integer getManagerId() {
return this.managerId;
}
public void setManagerId(Integer managerId) {
this.managerId = managerId;
}
public Location getLocation() {
return this.location;
}
public void setLocation(Location location) {
this.location = location;
}
public List<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public Employee addEmployee(Employee employee) {
getEmployees().add(employee);
employee.setDepartment(this);
return employee;
}
public Employee removeEmployee(Employee employee) {
getEmployees().remove(employee);
employee.setDepartment(null);
return employee;
}
}
\ No newline at end of file
package com.example.demo.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import jakarta.persistence.*;
/**
* The persistent class for the employees database table.
*
*/
@Entity
@Table(name="employees")
@NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name="EMPLOYEES_EMPLOYEEID_GENERATOR", sequenceName="EMPLOYEES_SEQ", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="EMPLOYEES_EMPLOYEEID_GENERATOR")
@Column(name="employee_id")
private Integer employeeId;
@Column(name="commission_pct")
private BigDecimal commissionPct;
private String email;
@Column(name="first_name")
private String firstName;
@Temporal(TemporalType.DATE)
@Column(name="hire_date")
private Date hireDate;
@Column(name="last_name")
private String lastName;
@Column(name="phone_number")
private String phoneNumber;
private BigDecimal salary;
//bi-directional many-to-one association to Department
@ManyToOne
@JoinColumn(name="department_id")
private Department department;
//uni-directional many-to-one association to Employee
@ManyToOne
@JoinColumn(name="manager_id")
private Employee manager;
//bi-directional many-to-one association to Job
@ManyToOne
@JoinColumn(name="job_id")
private Job job;
public Employee() {
}
public Integer getEmployeeId() {
return this.employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public BigDecimal getCommissionPct() {
return this.commissionPct;
}
public void setCommissionPct(BigDecimal commissionPct) {
this.commissionPct = commissionPct;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public Date getHireDate() {
return this.hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return this.phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public BigDecimal getSalary() {
return this.salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Employee getManager() {
return this.manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
public Job getJob() {
return this.job;
}
public void setJob(Job job) {
this.job = job;
}
}
\ No newline at end of file
package com.example.demo.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import jakarta.persistence.*;
/**
* The persistent class for the jobs database table.
*
*/
@Entity
@Table(name="jobs")
@NamedQuery(name="Job.findAll", query="SELECT j FROM Job j")
public class Job implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="job_id")
private String jobId;
@Column(name="job_title")
private String jobTitle;
@Column(name="max_salary")
private BigDecimal maxSalary;
@Column(name="min_salary")
private BigDecimal minSalary;
//bi-directional many-to-one association to Employee
@OneToMany(mappedBy="job")
private List<Employee> employees;
public Job() {
}
public String getJobId() {
return this.jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getJobTitle() {
return this.jobTitle;
}
public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}
public BigDecimal getMaxSalary() {
return this.maxSalary;
}
public void setMaxSalary(BigDecimal maxSalary) {
this.maxSalary = maxSalary;
}
public BigDecimal getMinSalary() {
return this.minSalary;
}
public void setMinSalary(BigDecimal minSalary) {
this.minSalary = minSalary;
}
public List<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public Employee addEmployee(Employee employee) {
getEmployees().add(employee);
employee.setJob(this);
return employee;
}
public Employee removeEmployee(Employee employee) {
getEmployees().remove(employee);
employee.setJob(null);
return employee;
}
}
\ No newline at end of file
package com.example.demo.model;
import java.io.Serializable;
import jakarta.persistence.*;
/**
* The persistent class for the locations database table.
*
*/
@Entity
@Table(name="locations")
@NamedQuery(name="Location.findAll", query="SELECT l FROM Location l")
public class Location implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name="LOCATIONS_LOCATIONID_GENERATOR", sequenceName="LOCATIONS_SEQ", allocationSize=100)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="LOCATIONS_LOCATIONID_GENERATOR")
@Column(name="location_id")
private Integer locationId;
private String city;
@Column(name="postal_code")
private String postalCode;
@Column(name="state_province")
private String stateProvince;
@Column(name="street_address")
private String streetAddress;
//uni-directional many-to-one association to Country
@ManyToOne
@JoinColumn(name="country_id")
private Country country;
public Location() {
}
public Integer getLocationId() {
return this.locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getPostalCode() {
return this.postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getStateProvince() {
return this.stateProvince;
}
public void setStateProvince(String stateProvince) {
this.stateProvince = stateProvince;
}
public String getStreetAddress() {
return this.streetAddress;
}
public void setStreetAddress(String streetAddress) {
this.streetAddress = streetAddress;
}
public Country getCountry() {
return this.country;
}
public void setCountry(Country country) {
this.country = country;
}
}
\ No newline at end of file
package com.example.demo.model;
import java.io.Serializable;
import java.util.List;
import jakarta.persistence.*;
/**
* The persistent class for the regions database table.
*
*/
@Entity
@Table(name="regions")
@NamedQuery(name="Region.findAll", query="SELECT r FROM Region r")
public class Region implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="region_id")
private Integer regionId;
@Column(name="region_name")
private String regionName;
//bi-directional many-to-one association to Country
@OneToMany(mappedBy="region")
private List<Country> countries;
public Region() {
}
public Integer getRegionId() {
return this.regionId;
}
public void setRegionId(Integer regionId) {
this.regionId = regionId;
}
public String getRegionName() {
return this.regionName;
}
public void setRegionName(String regionName) {
this.regionName = regionName;
}
public List<Country> getCountries() {
return this.countries;
}
public void setCountries(List<Country> countries) {
this.countries = countries;
}
public Country addCountry(Country country) {
getCountries().add(country);
country.setRegion(this);
return country;
}
public Country removeCountry(Country country) {
getCountries().remove(country);
country.setRegion(null);
return country;
}
}
\ No newline at end of file
package com.example.demo.wstrzykiwanie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FabrykaKomponentow {
{ System.out.println("FabrykaKomponentow init"); }
@Bean
Komponent dajKomponent() {
System.out.println("Zaraz utworzę Komponent w klasie FabrykaKomponentow");
return new Komponent();
}
}
package com.example.demo.wstrzykiwanie;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Inject1 {
// 1. sposób wstrzykiwania: pole
@Autowired
private Komponent komponent;
@Autowired
private Repo repo;
{ System.out.println("Inject1 init"); } // initialization block
public Inject1() {
System.out.println("Inject1 constr, komponent = " + komponent); // null
}
@PostConstruct
public void pc() {
System.out.println("inject1 @PostConstruct, komponent = " + komponent);
}
@RequestMapping("/inject1")
@ResponseBody
public String get() {
return repo.getText() + " " + komponent.getValue();
}
}
package com.example.demo.wstrzykiwanie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Inject2 {
{ System.out.println("Inject2 init"); }
// 2. sposób wstrzykiwania: setter
private Komponent komponent;
private Repo repo;
public Komponent getKomponent() {
return komponent;
}
@Autowired
public void setKomponent(Komponent komponent) {
System.out.println("SET KOMPONENT");
this.komponent = komponent;
}
public Repo getRepo() {
return repo;
}
@Autowired
public void setRepo(Repo repo) {
this.repo = repo;
}
@RequestMapping("/inject2")
@ResponseBody
public String get() {
return repo.getText() + " " + komponent.getValue();
}
}
package com.example.demo.wstrzykiwanie;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Inject3 {
{ System.out.println("Inject3 init"); }
// 3. sposób wstrzykiwania: konstruktor
// To podejście zwykle jest podawane jako najlepsze, bo umożliwia łatwą podmianę komponentów na "mocki" podczas testów
// Przy tym podejściu problemem byłaby jednak cykliczna zależność między komponentami.
private Komponent komponent;
private Repo repo;
// Zauważmy, że ta klasa nie jest już poprawnym "JavaBean", bo nie posiada konstruktora domyślnego.
// Adnotacja Autowired tym razem nie jest potrzebna.
public Inject3(Komponent komponent, Repo repo) {
System.out.println("KONSTRUKTOR Inject3(komponent, repo); komponent = " + komponent);
this.komponent = komponent;
this.repo = repo;
}
@RequestMapping("/inject3")
@ResponseBody
public String get() {
return repo.getText() + " " + komponent.getValue();
}
}
package com.example.demo.wstrzykiwanie;
import java.util.concurrent.atomic.AtomicInteger;
public class Komponent {
{ System.out.println("Komponent init"); }
private AtomicInteger licznik = new AtomicInteger();
public int getValue() {
return licznik.incrementAndGet();
}
}
package com.example.demo.wstrzykiwanie;
import org.springframework.stereotype.Repository;
@Repository // na podobnych zasadach: @Component, @Service, @Repository - tworzony jest jeden obiekt "singleton"
public class Repo {
{ System.out.println("Repo init"); }
public String getText() {
return "Ala ma kota";
}
}
spring.application.name=PC36-SpringTechnicznie
spring.datasource.url=jdbc:postgresql://localhost:5432/hr
spring.datasource.username=alx
spring.datasource.password=abc123
spring.jpa.show-sql=true
body {
background-color: #FFFFCC;
font-family: 'Arial', sans-serif;
}
h1 {
color: green;
text-align: center;
}
form {
margin: 30px auto;
padding: 20px;
width: 800px;
border: 4px solid blue;
background-color: #AAEEFF;
}
.wynik {
background-color: #FFFFFF;
border: 3px solid green;
margin: 20px auto;
width: 800px;
padding: 10px;
color: green;
}
.error {
background-color: #FFFFFF;
border: 6px double red;
margin: 20px auto;
padding: 10px;
width: 800px;
color: red;
font-weight: bold;
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Employees</title>
<style type="text/css">
table {
border-collapse: collapse;
}
th, td {
border: 1px solid #444444;
padding: 4px;
}
</style>
</head>
<body>
<table>
<tr>
<th>Imię</th><th>Nazwisko</th><th>Stanowisko</th><th>Pensja</th><th>Departament</th><th>Miasto</th>
</tr>
<tr th:each="emp : ${emps}">
<td th:text="${emp.firstName}">firstName</td>
<td th:text="${emp.lastName}">lastName</td>
<td th:text="${emp.job.jobTitle}">jobTitle</td>
<td th:text="${emp.salary}">salary</td>
<td th:text="${emp.department.departmentName}" th:if="${emp.department != null}">departmentName</td>
<td th:text="${emp.department.location.city}" th:if="${emp.department != null}">city</td>
</tr>
</table>
<p><a th:href="@{/}">wróć do spisu treści</a></p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<p>[[${txt}]]</p>
<p>Teraz jest godzina: [[${time}]]</p>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spis treści</title>
<link rel="stylesheet" type="text/css" th:href="@{/styl.css}" href="../static/styl.css">
</head>
<body>
<h1>Spis treści</h1>
<ul>
<li><a href="/hello">Hello</a></li>
<li><a href="/ping">Ping</a></li>
</ul>
<h2>Spring Data</h2>
<ul>
<li><a href="/emps0">InMemoryRepository</a></li>
<li><a href="/emps1">emps1</a> - wersja z bespośrednio użytym JPA</li>
<li><a href="/emps1/100">emps1/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps2">emps2</a> - wersja z użyciem JPA wyciągniętym do osobnej klasy @Repository</li>
<li><a href="/emps2/100">emps2/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps2/by_name?name=King">emps2/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps3">emps3</a> - j.w. ale interfejs</li>
<li><a href="/emps3/100">emps3/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps3/by_name?name=King">emps3/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps4">emps4</a> - Spring Data JpaRepository – domyślny interfejs</li>
<li><a href="/emps4/100">emps4/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps5/all">emps5</a> - Spring Data JpaRepository – rozszerzony interfejs</li>
<li><a href="/emps5/by_id/101">emps5/by_id/101</a> - wg id</li>
<li><a href="/emps5/by_name?name=King">emps5/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps5/by_job/ST_CLERK">/by_job/ST_CLERK</a> - wg stanowiska
<li><a href="/emps5/by_city/Seattle">emps5/by_city/Seattle</a> - wg miasta</li>
<li><a href="/emps5/by_salary?min=5000&amp;max=10000">emps5/by_salary</a> - wg pensji</li>
<li><a href="/emps5/by_year/1999">emps5/by_year</a> - wg roku zatrudneinia - przykład <strong>native query</strong></li>
<li><a href="/emps5/szef/105">szef/105</a> - nazwisko sefa (przykład własnej funkcji)
<li><a href="/emps5/zara?id=103">zara?id=103</a> - zarabiający więcej niż (przykład własnej funkcji)
<li><a href="/emps5/move/110?dep=90&job=AD_PRES">move</a> - przenieś pracownika
</ul>
<h2>Wstrzykiwanie na 3 sposoby</h2>
<ul>
<li><a href="/inject1">Wstrzykiwanie 1</a> - pole</li>
<li><a href="/inject2">Wstrzykiwanie 2</a> - setter</li>
<li><a href="/inject3">Wstrzykiwanie 3</a> - konstruktor</li>
</ul>
<h2>Eksperymenty z beanami</h2>
<ul>
<li><a href="/test0">Test 0</a> &mdash; brak modelu</li>
<li><a href="/test1">Test 1</a> &mdash; <code>Model</code></li>
<li><a href="/test2">Test 2</a> &mdash; parametr metody i <code>Model</code></li>
<li><a href="/test3">Test 3</a> &mdash; parametr <code>@ModelAttribute</code></li>
<li><a href="/test4">Test 4</a> &mdash; <code>@ModelAttribute</code> przy metodzie i w parametrze</li>
<li><a href="/test4a">Test 4a</a> &mdash; <code>@ModelAttribute</code> przy metodzie, ale nie w parametrze</li>
<li><a href="/test5">Test 5</a> &mdash; <code>@ModelAttribute</code> w połączeniu z <code>@SessionAttributes</code></li>
<li><a href="/test6">Test 6</a> &mdash; <code>@Component</code> w połączeniu z <code>@Autowired</code></li>
<li><a href="/test7">Test 7</a> &mdash; <code>@Component @Scope(session)</code></li>
<li><a href="/test8">Test 8</a> &mdash; <code>@Bean</code> w połączeniu z <code>@Autowired</code></li>
</ul>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Test beanów za pomocą licznika</title>
<link rel="stylesheet" type="text/css" th:href="@{/styl.css}"/>
</head>
<body>
<h1>Test beanów za pomocą licznika</h1>
<p>licznik = <strong th:text="${licznik}">X</strong></p>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Names</title>
</head>
<body>
<ul>
<li th:each="name : ${names}" th:text="${name}">ktoś</li>
</ul>
<p><a th:href="@{/}">wróć do spisu treści</a></p>
</body>
</html>
<!DOCTYPE html>
<html lang="pl" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Ping</title>
<link rel="stylesheet" type="text/css" th:href="@{/styl.css}" href="../static/styl.css">
</head>
<body>
<h2>Informacje o kliencie</h2>
<ul>
<li>Adres: <strong th:text="${clientInfo.ip}">1.2.3.4</strong></li>
<li>Przeglądarka: <strong th:text="${clientInfo.userAgent}">IE</strong></li>
<li>Data: <strong th:text="${clientInfo.data}">data</strong></li>
</ul>
</body>
</html>
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Pc36SpringTechnicznieApplicationTests {
@Test
void contextLoads() {
}
}
target/
.settings/
.classpath
.project
*.iml
.idea/
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.alx.kjava</groupId>
<artifactId>Wielomodulowy</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>wielomodulowy-model</module>
<module>wielomodulowy-baza</module>
<module>wielomodulowy-rest</module>
<module>wielomodulowy-klient_rest</module>
<module>wielomodulowy-web</module>
<module>wielomodulowy-ear</module>
<module>wielomodulowy-soap_serwer</module>
<module>wielomodulowy-soap_klient</module>
<module>wielomodulowy-soap_api</module>
</modules>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>pl.alx.kjava</groupId>
<artifactId>Wielomodulowy</artifactId>
<version>1.0</version>
</parent>
<artifactId>wielomodulowy-baza</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
package sklep.db;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import sklep.exn.DBException;
import sklep.exn.RecordNotFound;
import sklep.model.Customer;
public class CustomerDAO {
private final DBConnection db;
CustomerDAO(DBConnection db) {
this.db = db;
}
public Customer findByEmail(String email) throws DBException, RecordNotFound {
final String sql = "SELECT * FROM customers WHERE customer_email = ?";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, email);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return customerFromRS(rs);
} else {
throw new RecordNotFound("Cannot find customer with email " + email);
}
}
} catch (SQLException e) {
throw new DBException("SQL error in CustomerDAO.findById: " + e.getMessage(), e);
}
}
public List<Customer> readAll() throws DBException {
final String sql = "SELECT * FROM customers";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
return customerListFromRS(rs);
}
} catch (SQLException e) {
throw new DBException("SQL error in CustomerDAO.readAll: " + e.getMessage(), e);
}
}
private List<Customer> customerListFromRS(ResultSet rs) throws SQLException {
List<Customer> records = new ArrayList<>();
while (rs.next()) {
Customer product = customerFromRS(rs);
records.add(product);
}
return records;
}
private Customer customerFromRS(ResultSet rs) throws SQLException {
return new Customer(
rs.getString("customer_email"),
rs.getString("customer_name"),
rs.getString("phone_number"),
rs.getString("address"),
rs.getString("postal_code"),
rs.getString("city"));
}
public void insert(Customer customer) throws DBException {
// używać gdy obiekt ma wpisane ID (tu: email)
final String sql = "INSERT INTO customers("
+ "customer_email, customer_name, phone_number, address, postal_code, city)"
+ " VALUES (?, ?, ?, ?, ?, ?)";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, customer.getEmail());
stmt.setString(2, customer.getName());
stmt.setString(3, customer.getPhoneNumber());
stmt.setString(4, customer.getAddress());
stmt.setString(5, customer.getPostalCode());
stmt.setString(6, customer.getCity());
stmt.executeUpdate();
} catch (SQLException e) {
throw new DBException("Error during INSERT CUSTOMER", e);
}
}
public boolean update(Customer customer) throws DBException {
final String sql = "UPDATE customers SET "
+ " customer_name=?, phone_number=?, address=?, postal_code=?, city=?"
+ " WHERE customer_email = ?";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, customer.getName());
stmt.setString(2, customer.getPhoneNumber());
stmt.setString(3, customer.getAddress());
stmt.setString(4, customer.getPostalCode());
stmt.setString(5, customer.getCity());
stmt.setString(6, customer.getEmail());
int count = stmt.executeUpdate();
return count > 0;
} catch (SQLException e) {
throw new DBException("Error during UPDATE CUSTOMER", e);
}
}
public void save(Customer customer) throws DBException {
if(customer.getEmail() == null) {
throw new IllegalArgumentException("Customer email cannot be null");
} else {
if(! update(customer)) {
insert(customer);
}
}
}
public boolean delete(String email) throws DBException {
final String sql = "DELETE FROM customers WHERE customer_email = ?";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, email);
int count = stmt.executeUpdate();
return count > 0;
} catch (SQLException e) {
throw new DBException("Error during DELETE CUSTOMER", e);
}
}
public boolean delete(Customer customer) throws DBException {
return delete(customer.getEmail());
}
}
package sklep.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import sklep.exn.DBException;
public class DBConnection implements AutoCloseable {
private Connection sqlConnection;
private DBConnection(Connection sqlConnection) {
this.sqlConnection = sqlConnection;
}
public static DBConnection open() throws DBException {
return open(false);
}
public static DBConnection open(boolean autoCommit) throws DBException {
try {
Properties props = DBSettings.load();
if(props.containsKey("driver_class")) {
Class.forName(props.getProperty("driver_class"));
}
Connection c = DriverManager.getConnection(props.getProperty("url") , props);
c.setAutoCommit(autoCommit);
return new DBConnection(c);
} catch (ClassNotFoundException | SQLException e) {
throw new DBException("Cannot connect to postgresql: " + e, e);
}
}
public static DBConnection openLocalhost() throws DBException {
try {
Connection c = DriverManager.getConnection("jdbc:postgresql://localhost/sklep", "kurs", "abc123");
c.setAutoCommit(false);
return new DBConnection(c);
} catch (SQLException e) {
throw new DBException("Cannot connect to postgresql: " + e, e);
}
}
@Override
public void close() {
try {
if (sqlConnection != null) {
sqlConnection.close();
sqlConnection = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getSqlConnection() {
return sqlConnection;
}
public void commit() throws DBException {
try {
sqlConnection.commit();
} catch (SQLException e) {
throw new DBException("Error during commit: " + e.getMessage(), e);
}
}
public void rollback() throws DBException {
try {
sqlConnection.rollback();
} catch (SQLException e) {
throw new DBException("Error during rollback: " + e.getMessage(), e);
}
}
public ProductDAO productDAO() {
return new ProductDAO(this);
}
public CustomerDAO customerDAO() {
return new CustomerDAO(this);
}
public OrderDAO orderDAO() {
return new OrderDAO(this);
}
}
package sklep.db;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import sklep.exn.DBException;
public class DBSettings {
public static final String DB_SETTINGS_SYSTEM_PROPERTY = "sklep.db_settings_location";
private static final String INTERNAL_DEFAULT_PROPERTIES = "/sklep.properties";
private static DBSettings dbSettings; // singleton
private final Properties props;
private DBSettings() throws DBException {
props = new Properties();
String systemProperty = System.getProperty(DB_SETTINGS_SYSTEM_PROPERTY);
try(InputStream input = systemProperty != null
? new FileInputStream(new File(systemProperty))
: DBSettings.class.getResourceAsStream(INTERNAL_DEFAULT_PROPERTIES) ) {
props.load(input);
} catch (IOException e) {
//e.printStackTrace();
throw new DBException("Cannot read settings. " + e, e);
}
}
public static synchronized DBSettings getInstance() throws DBException {
// Dla klasy typu "singleton" w aplikacji powstaje tylko jedna instancja (obiekt) tej klasy.
// Dostęp do tego obiektu odbywa się poprzez metodę statyczną taką jak ta.
// Tutaj mamy "leniwą inicjalizację", czyli obiekt jest tworzony przy pierwszej próbie dostepu.
if(dbSettings == null) {
dbSettings = new DBSettings();
}
return dbSettings;
}
public Properties getProperties() {
return props;
}
public static Properties load() throws DBException {
return getInstance().getProperties();
}
}
package sklep.db;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import sklep.exn.DBException;
import sklep.exn.RecordNotFound;
import sklep.model.Order;
import sklep.model.OrderProduct;
public class OrderDAO {
private static final String[] ID_COLUMNS = {"order_id", "order_date"};
private final DBConnection db;
OrderDAO(DBConnection db) {
this.db = db;
}
public Order findById(int orderId) throws DBException, RecordNotFound {
final String sql = "SELECT * FROM orders WHERE order_id = ?";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setInt(1, orderId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return orderFromRS(rs);
} else {
throw new RecordNotFound("Cannot find order with id " + orderId);
}
}
} catch (SQLException e) {
throw new DBException("SQL error in OrderDAO.findById: " + e.getMessage(), e);
}
}
public List<Order> readAll() throws DBException {
final String sql = "SELECT * FROM orders ORDER BY order_id";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
return orderListFromRS(rs);
}
} catch (SQLException e) {
throw new DBException("SQL error in OrderDAO.readAll: " + e.getMessage(), e);
}
}
public List<Order> customerOrders(String email) throws DBException {
final String sql = "SELECT * FROM orders WHERE customer_email = ? ORDER BY order_id";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, email);
try (ResultSet rs = stmt.executeQuery()) {
return orderListFromRS(rs);
}
} catch (SQLException e) {
throw new DBException("SQL error in OrderDAO.customerOrders: " + e.getMessage(), e);
}
}
private List<Order> orderListFromRS(ResultSet rs) throws SQLException, DBException {
List<Order> orders = new ArrayList<>();
while (rs.next()) {
Order order = orderFromRS(rs);
orders.add(order);
}
return orders;
}
private Order orderFromRS(ResultSet rs) throws SQLException, DBException {
Order order = Order.ofDbFields(
rs.getInt("order_id"),
rs.getString("customer_email"),
rs.getTimestamp("order_date"),
rs.getString("status"));
order.addProducts(orderProductsForOrder(order.getOrderId()));
return order;
}
List<OrderProduct> orderProductsForOrder(int orderId) throws DBException {
final String sql = "SELECT * FROM order_products WHERE order_id = ? ORDER BY product_id";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setInt(1, orderId);
try (ResultSet rs = stmt.executeQuery()) {
List<OrderProduct> ops = new ArrayList<>();
while(rs.next()) {
ops.add(orderProductFromRS(rs));
}
return ops;
}
} catch (SQLException e) {
throw new DBException("SQL error in OrderDAO.customerOrders: " + e.getMessage(), e);
}
}
private OrderProduct orderProductFromRS(ResultSet rs) throws SQLException {
return new OrderProduct(rs.getInt("order_id"), rs.getInt("product_id"), rs.getInt("quantity"), rs.getBigDecimal("actual_price"));
}
}
package sklep.db;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import sklep.exn.DBException;
import sklep.exn.RecordNotFound;
import sklep.model.Product;
/* DAO - Data Access Object(s)
Dostęp do baz danych oparty o takie zasady:
tabelom bazodanowym odpowiadają klasy w naszej aplikacji
np. dla tabeli products mamy klasę Product (w pakiecie model)
dla takie pary tabela products + klasa Product tworzymy klasę narzędziową ProductDAO , której zadaniem jest obsługa tej tabeli: odczyt, zapis, wyszukiwanie, i inne operacje jeśli są potrzebne.
*/
public class ProductDAO {
private static final BigDecimal MAX_PRICE = new BigDecimal(1_000_000_000);
private static final String[] ID_COLUMNS = {"product_id"};
private final DBConnection db;
ProductDAO(DBConnection db) {
this.db = db;
}
public Product findById(int productId) throws DBException, RecordNotFound {
final String sql = "SELECT * FROM products WHERE product_id = ?";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setInt(1, productId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return productFromRS(rs);
} else {
throw new RecordNotFound("Cannot find product with id " + productId);
}
}
} catch (SQLException e) {
throw new DBException("SQL error in ProductDAO.findById: " + e.getMessage(), e);
}
}
public List<Product> readAll() throws DBException {
final String sql = "SELECT * FROM products ORDER BY product_id";
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
return productListFromRS(rs);
}
} catch (SQLException e) {
throw new DBException("SQL error in ProductDAO.readAll: " + e.getMessage(), e);
}
}
public List<Product> findByPrice(BigDecimal minPrice, BigDecimal maxPrice) throws DBException {
final String sql = "SELECT * FROM products WHERE price BETWEEN ? AND ? ORDER BY product_id";
if(minPrice == null)
minPrice = BigDecimal.ZERO;
if(maxPrice == null)
maxPrice = MAX_PRICE;
try (PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setBigDecimal(1, minPrice);
stmt.setBigDecimal(2, maxPrice);
try (ResultSet rs = stmt.executeQuery()) {
return productListFromRS(rs);
}
} catch (SQLException e) {
throw new DBException("SQL error in ProductDAO.findByPrice: " + e.getMessage(), e);
}
}
private List<Product> productListFromRS(ResultSet rs) throws SQLException {
List<Product> products = new ArrayList<>();
while (rs.next()) {
Product product = productFromRS(rs);
products.add(product);
}
return products;
}
private Product productFromRS(ResultSet rs) throws SQLException {
return new Product(
rs.getInt("product_id"),
rs.getString("product_name"),
rs.getBigDecimal("price"),
rs.getBigDecimal("vat"),
rs.getString("description"));
}
public void insert(Product product) throws DBException {
// używać gdy obiekt ma wpisane ID
final String sql = "INSERT INTO products("
+ " product_id, product_name, price, vat, description)"
+ " VALUES (?, ?, ?, ?, ?)";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setInt(1, product.getProductId());
stmt.setString(2, product.getProductName());
stmt.setBigDecimal(3, product.getPrice());
stmt.setBigDecimal(4, product.getVat());
stmt.setString(5, product.getDescription());
stmt.executeUpdate();
} catch (SQLException e) {
throw new DBException("Error during INSERT PRODUCT", e);
}
}
public void insertNew(Product product) throws DBException {
// używać gdy obiekt nie ma wpisanego ID (productID == null)
final String sql = "INSERT INTO products("
+ " product_name, price, vat, description)"
+ " VALUES (?, ?, ?, ?)";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql, ID_COLUMNS)) {
stmt.setString(1, product.getProductName());
stmt.setBigDecimal(2, product.getPrice());
stmt.setBigDecimal(3, product.getVat());
stmt.setString(4, product.getDescription());
stmt.executeUpdate();
try (ResultSet rs = stmt.getGeneratedKeys()) {
if(rs.next()) {
// w obiekcie, który mamy w pamięci, uzupełniamy brakujące ID na podstawie tego, co wygenerowała baza
product.setProductId(rs.getInt(1));
}
};
} catch (SQLException e) {
throw new DBException("Error during INSERT PRODUCT", e);
}
}
public boolean update(Product product) throws DBException {
final String sql = "UPDATE products SET "
+ " product_name = ?, price = ?, vat = ?, description = ?"
+ " WHERE product_id = ?";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setString(1, product.getProductName());
stmt.setBigDecimal(2, product.getPrice());
stmt.setBigDecimal(3, product.getVat());
stmt.setString(4, product.getDescription());
stmt.setInt(5, product.getProductId());
int count = stmt.executeUpdate();
return count > 0;
} catch (SQLException e) {
throw new DBException("Error during UPDATE PRODUCT", e);
}
}
public void save(Product product) throws DBException {
if(product.getProductId() == null) {
// wstawiamy nowy rekord korzystajac z sekwecji
insertNew(product);
} else {
if(! update(product)) {
insert(product);
}
}
}
public boolean delete(int productId) throws DBException {
final String sql = "DELETE FROM products WHERE product_id = ?";
try(PreparedStatement stmt = db.getSqlConnection().prepareStatement(sql)) {
stmt.setInt(1, productId);
int count = stmt.executeUpdate();
return count > 0;
} catch (SQLException e) {
throw new DBException("Error during DELETE PRODUCT", e);
}
}
public boolean delete(Product product) throws DBException {
return delete(product.getProductId());
}
}
package sklep.db;
import java.util.List;
import sklep.exn.DBException;
import sklep.model.Product;
public class ZwyklyOdczyt_DAO {
public static void main(String[] args) {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
List<Product> products = productDAO.readAll();
for (Product product : products) {
System.out.println(product);
}
} catch (DBException e) {
e.printStackTrace();
}
}
}
package sklep.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ZwyklyOdczyt_JDBC {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/sklep";
String sql = "SELECT * FROM products";
try(Connection c = DriverManager.getConnection(url, "kurs", "abc123");
PreparedStatement stmt= c.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
while(rs.next()) {
System.out.printf("%d: %s za cenę %s\n",
rs.getInt("product_id"), rs.getString("product_name"), rs.getBigDecimal("price"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
url=jdbc:postgresql://localhost:5432/sklep
driver_class=org.postgresql.Driver
user=kurs
password=abc123
photo_dir=/home/patryk/sklep/foto
# Sciezki na Windows: albo piszemy slashe / , albo podwojne backslashe \\
# photo_dir=C:/Users/Patryk/Desktop/sklep/foto
# photo_dir=C:\\Users\\Patryk\\Desktop\\sklep\\foto
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>pl.alx.kjava</groupId>
<artifactId>Wielomodulowy</artifactId>
<version>1.0</version>
</parent>
<artifactId>wielomodulowy-ear</artifactId>
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-web</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-rest</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-soap_serwer</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>pl.alx.kjava</groupId>
<artifactId>Wielomodulowy</artifactId>
<version>1.0</version>
</parent>
<artifactId>wielomodulowy-klient_rest</artifactId>
<properties>
<resteasy.version>6.2.6.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class Klient01_URL {
public static void main(String[] args) {
// Najprostszy sposób w Javie, aby pobrać dane z adresu URL, to użyć klasy URL.
try {
URL url = new URL("http://localhost:8080/PC35-RestSerwer/products.json");
System.out.println("Odczytuję dane...");
try (InputStream input = url.openStream()) {
// teraz z inputa możemy czytać ciąg bajtów
// ja przerzucę bajty czytane z sieci bezpośrednio do System.out
// (w przypadku obcego serwisu może być to niebezpieczne)
input.transferTo(System.out);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
public class Klient02_URL_JSON {
public static void main(String[] args) {
try {
URL url = new URL(Ustawienia.ADRES_USLUGI + "/products.json");
try(InputStream inputStream = url.openStream();
JsonReader reader = Json.createReader(inputStream)) {
JsonArray array = reader.readArray();
// System.out.println(array);
for(JsonValue jsonValue : array) {
//System.out.println(jsonValue);
System.out.println(jsonValue.asJsonObject().getString("productName"));
System.out.println(" opis: " + jsonValue.asJsonObject().getString("description", ""));
System.out.println(" cena: " + jsonValue.asJsonObject().getJsonNumber("price").bigDecimalValue());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Klient03_HttpClient {
/* W Java 11 pojawiło się rozwiązanie "HttpClient", które umożliwia komunikację HTTP z dużą kontrolą nad szczegółami.
* Wysyłając zapytanie, od razu trzeba podać odpowiedni "BodyHandler",
* który pozwoli nam odczytać treść odpowiedzi we właściwy dla nas sposób.
*
* W tej wersji wynik jest zapisywany do pliku.
*/
public static void main(String[] args) {
HttpClient httpClient = HttpClient.newHttpClient();
try {
URI uri = new URI(Ustawienia.ADRES_USLUGI + "/products.json");
HttpRequest request = HttpRequest.newBuilder(uri).build();
HttpResponse<Path> response = httpClient.send(request, BodyHandlers.ofFile(Paths.get("wynik03.json")));
System.out.println("response " + response);
System.out.println("status: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("BRAK"));
System.out.println("OK, zapisany plik: " + response.body());
} catch (URISyntaxException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class Klient04_HttpClient_String {
public static void main(String[] args) {
HttpClient httpClient = HttpClient.newHttpClient();
try {
URI uri = new URI(Ustawienia.ADRES_USLUGI + "/products.json");
HttpRequest request = HttpRequest.newBuilder(uri).build();
// Body z odpowiedzi pobierzemy jako obiekt String z całą treścią
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
System.out.println("response " + response);
System.out.println("status: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("BRAK"));
System.out.println("Treść odpowiedzi:\n" + response.body()); // tutaj
} catch (URISyntaxException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class Klient05_HttpClient_Accept {
public static void main(String[] args) {
HttpClient httpClient = HttpClient.newHttpClient();
try {
URI uri = new URI(Ustawienia.ADRES_USLUGI + "/products");
// W tej wersji do zapytania dodajemy nagłówek Accept
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Accept", "text/plain")
.build();
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
System.out.println("response " + response);
System.out.println("status: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("BRAK"));
System.out.println("Treść odpowiedzi:\n" + response.body());
} catch (URISyntaxException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
public class Klient06_HttpClient_JSON {
/* W tej wersji używamy technologii Jakarta JSON P.
*
* Widzimy drzewo danych jsonowych i jego elementytakie jak JsonObject, JsonArray, ...
* Mamy dostęp do poszczególnych pól.
*/
public static void main(String[] args) {
HttpClient httpClient = HttpClient.newHttpClient();
try {
URI uri = new URI(Ustawienia.ADRES_USLUGI + "/products/1");
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Accept", "application/json")
.build();
HttpResponse<InputStream> response = httpClient.send(request, BodyHandlers.ofInputStream());
System.out.println("response " + response);
System.out.println("status: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("BRAK"));
JsonReader reader = Json.createReader(response.body());
JsonObject product = reader.readObject();
System.out.println("Pobrany obiekt jsonowy: " + product);
String nazwa = product.getString("productName");
String opis = product.getString("description", "BRAK OPISU");
BigDecimal cena = product.getJsonNumber("price").bigDecimalValue();
System.out.println(nazwa + " za cenę " + cena + " , opis: " + opis);
reader.close();
} catch (URISyntaxException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
public class Klient07_HttpClient_JSON_Lista {
public static void main(String[] args) {
try {
JsonArray array = pobierzJsona(Ustawienia.ADRES_USLUGI + "/products.json");
for(JsonValue jsonValue : array) {
JsonObject jsonObject = jsonValue.asJsonObject();
System.out.println(jsonObject.getString("productName"));
if(jsonObject.containsKey("description")) {
System.out.println(" opis: " + jsonObject.getString("description", ""));
}
System.out.println(" cena: " + jsonObject.getJsonNumber("price").bigDecimalValue());
}
} catch (IOException | InterruptedException | URISyntaxException e) {
e.printStackTrace();
}
}
private static JsonArray pobierzJsona(String adres) throws IOException, InterruptedException, URISyntaxException {
HttpClient httpClient = HttpClient.newHttpClient();
URI uri = new URI(adres);
HttpRequest request = HttpRequest.newBuilder(uri).build();
HttpResponse<InputStream> response = httpClient.send(request, BodyHandlers.ofInputStream());
System.out.println("response " + response);
System.out.println("status: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("BRAK"));
return wczytajJsona(response.body());
}
private static JsonArray wczytajJsona(InputStream input) {
try(JsonReader reader = Json.createReader(input)) {
return reader.readArray();
}
}
}
package rest_klient;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
// Ten i kolejne przykłady pokazują jak aplikacja kliencka napisana w Javie może wysyłać
// zapytania do usługi REST-owej (głównie GET, jest też gdzieś POST)
// korzystając z technologii JAX-RS "po stronie klienta".
// Aby z tego skorzystać, do projektu trzeba dodać bibliotekę z implementacją JAX-RS.
// Tutaj jest to resteasy-client.
public class Klient11_RestClient {
public static void main(String[] args) {
System.out.println("Startujemy");
Client client = ClientBuilder.newClient();
System.out.println("Przygotowuję zapytanie");
WebTarget target = client.target(Ustawienia.ADRES_USLUGI).path("products.json");
Invocation invocation = target.request().buildGet();
System.out.println("Wysyłam zapytanie");
Response response = invocation.invoke();
// Wynikiem jest obiekt klasy Response - tej samej, co na serwerze (używaliśmy np. do generowania kodów 404).
// W obiekcie można sprawdzić informacji o odpowiedzi: media type, status code.
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// Aby odczytać zawartość zwróconą przez serwer, używamy metody readEntity.
// (przy domyślnych ustawieniach) tę metodę można wywołać tylko raz.
// Dopiero w tym momencie podajemy typ, na który zostanie skonwertowana treść odpowiedzi
// (w miarę możliwości - po prostu niektóre typy zadziałają, a niektóre nie).
byte[] dane = response.readEntity(byte[].class);
System.out.println("Dane mają " + dane.length + " bajtów.");
try {
Files.write(Paths.get("wynik11.json"), dane);
System.out.println("Zapisałem w pliku");
} catch (IOException e) {
System.err.println(e);
}
System.out.println("Koniec");
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
public class Klient12_RestClient_String {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
// Taki styl programowania to "fluent API"
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.json")
.request()
.buildGet()
.invoke();
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// readEntity(OKREŚLENIE TYPU) stara się odczytać tresc odpowiedzi jako obiekt podanego typu
// Obsługiwane typy to m.in: byte[], String, InputStream, File
// Dodając odpowiednie "MeassgeBodyReader", możemy obsługiwać dowolne typy.
// W szczególności, gdy dodamy do projektu obsługę XML lub JSON (zob. zależności Mavena),
// będziemy mogli odczytywać dane w postaci obiektów naszego modelu, np. Product.
String dane = response.readEntity(String.class);
System.out.println("Otrzymane dane:");
System.out.println(dane);
}
}
package rest_klient;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import javax.swing.JOptionPane;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
public class Klient13_RestClient_Multiformat {
public static void main(String[] args) {
try {
Client client = ClientBuilder.newClient();
String[] formaty = {"txt", "json", "xml", "html", "pdf"};
String format = (String) JOptionPane.showInputDialog(null, "Wybierz format danych", "Wybór",
JOptionPane.QUESTION_MESSAGE, null, formaty, "txt");
if(format == null) {
return;
}
String mediaType = switch(format) {
case "txt" -> "text/plain";
case "json" -> "application/json";
case "xml" -> "application/xml";
case "html" -> "text/html";
case "pdf" -> "application/pdf";
default -> throw new IllegalArgumentException();
};
// Klient może wybrać format (mediaType), w jakim oczekuje odpowiedzi - to wpływa na nagłówek Accept
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.request(mediaType)
.buildGet()
.invoke();
JOptionPane.showMessageDialog(null, String.format("""
Status: %d
C-Type: %s
Length: %d""", response.getStatus(), response.getMediaType(), response.getLength()));
Path plik = Paths.get("wynik13." + format);
InputStream stream = response.readEntity(InputStream.class);
Files.copy(stream, plik, StandardCopyOption.REPLACE_EXISTING);
JOptionPane.showMessageDialog(null, "Zapisano plik " + plik);
} catch(Exception e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
public class Klient14_RestClient_PDF {
private static final MediaType PDF_TYPE = new MediaType("application", "pdf");
public static void main(String[] args) {
int productId = 1;
System.out.println("Startujemy...");
Client client = ClientBuilder.newClient();
WebTarget root = client.target(Ustawienia.ADRES_USLUGI);
Response response = root
.path("products")
.path("{id}")
.resolveTemplate("id", productId)
.request()
.accept(PDF_TYPE)
.buildGet()
.invoke();
System.out.println("Otrzymałem response: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("Content-Type: " + response.getMediaType());
if(response.getStatus() != 200) {
System.out.println("Chyba coś nie tak, więc przerywam.");
return;
}
String nazwaPliku = "wynik.pdf";
String contentDisposition = response.getHeaderString("Content-Disposition");
if(contentDisposition != null && contentDisposition.contains(";filename=")) {
nazwaPliku = contentDisposition.split(";filename=")[1];
}
try(InputStream strumienDanych = response.readEntity(InputStream.class)) {
long ileBajtow = Files.copy(strumienDanych, Paths.get(nazwaPliku), StandardCopyOption.REPLACE_EXISTING);
System.out.printf("Zapisano %d bajtów do pliku %s\n", ileBajtow, nazwaPliku);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Gotowe");
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
import sklep.model.ProductList;
public class Klient21_RestClient_JAXB {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.xml")
.request()
.buildGet()
.invoke();
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
ProductList products = response.readEntity(ProductList.class);
System.out.println("Otrzymane dane:");
for (Product product : products.getProducts()) {
System.out.println(product);
}
}
}
package rest_klient;
import java.util.List;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
public class Klient22_RestClient_JSON {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.json")
.request()
.buildGet()
.invoke();
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// Ponieważ wersja JSON na serwerze zwraca wynik typu List<Product>, to tutaj musimy podać "typ generyczny",
// a nie wystarczy zwykła klasa.
// Nie zadziała:
// List<Product> products = response.readEntity(List.class);
GenericType<List<Product>> typListy = new GenericType<>() {};
List<Product> products = response.readEntity(typListy);
// albo jednolinijkowo:
// List<Product> products = response.readEntity(new GenericType<List<Product>>() {});
for(Product product : products) {
System.out.println(product);
}
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
public class Klient23_RestClient_JSON_JedenProdukt {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.path("1")
.request()
.accept(MediaType.APPLICATION_JSON)
.buildGet()
.invoke();
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
Product product = response.readEntity(Product.class);
System.out.println("Odczytany produkt: " + product);
}
}
package rest_klient;
import java.math.BigDecimal;
import java.util.Scanner;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
public class Klient24_Interaktywna_Edycja {
public static void main(String[] args) {
System.out.println("Startujemy...");
Scanner scanner = new Scanner(System.in);
Client client = ClientBuilder.newClient();
WebTarget path = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.path("{id}");
System.out.println("Przygotowana ścieżka: " + path);
while (true) {
System.out.print("\nPodaj id: ");
int id = scanner.nextInt();
if(id == 0) break;
Response response = path
.resolveTemplate("id", id)
.request(MediaType.APPLICATION_JSON)
.get();
System.out.println("Status: " + response.getStatus());
System.out.println("Content-Type: " + response.getMediaType());
if (response.getStatus() == 200) {
Product product = response.readEntity(Product.class);
System.out.println("Mam produkt:");
System.out.println(" Nazwa: " + product.getProductName());
System.out.println(" Cena: " + product.getPrice());
System.out.println(" Opis: " + product.getDescription());
System.out.println();
System.out.println("Podaj zmianę ceny (0 aby nie zmieniać):");
BigDecimal zmianaCeny = scanner.nextBigDecimal();
if(zmianaCeny.compareTo(BigDecimal.ZERO) != 0) {
BigDecimal newPrice = product.getPrice().add(zmianaCeny);
System.out.println("PUT nowej ceny...");
Response odpPut = path.path("price").resolveTemplate("id", id).request()
.put(Entity.entity(newPrice, MediaType.TEXT_PLAIN_TYPE));
System.out.println("PUT zakończył się kodem " + odpPut.getStatus());
}
} else {
System.out.println("nie mogę odczytać");
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment