Hibernate - Nie mogę ogarnąc prostej relacji one to one.

Hibernate - Nie mogę ogarnąc prostej relacji one to one.
s-kaczmarek
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:16
1

Cześć, uczę się hibernate'a i relacji pomiędzy tabelami. Mam dwie encje - "Contact", która zawiera pola: id, imię i email oraz "Group", która zawiera pola id i nazwę grupy. Chcę zrobić prostą relację - każdy kontakt ma przypisaną jedną grupę (wiem, że to trochę nie logiczne, ale chcę pomału przećwiczyć wszystkie relacje). Ogólnie mi to wszystko nie działa i nie rozumiem dlaczego. Proszę o pomoc.

Kod wygląda następująco:

encja Kontakt:

Kopiuj
package domain;

import javax.persistence.*;
import java.lang.reflect.Type;

@Entity
@Table(name = "contact")
public class Contact {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String email;

    @OneToOne(mappedBy = "contact", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Group group;

    public Contact(){}

    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }

    @Override
    public String toString() {
        return "Contact{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", group=" + group +
                '}';
    }

    // Getters and Setters

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }
}

encja Grupy:

Kopiuj

package domain;

import javax.persistence.*;

@Entity
@Table(name = "group")
public class Group {

    @Id
    //@GeneratedValue
    private int groupId;

    private String groupName;

    @OneToOne
    @MapsId
    private Contact contact;

    // Constructors

    public Group(){}

    public Group(String groupName) {
        this.groupName = groupName;
    }

    // Getters and Setters


    public int getGroupId() {
        return groupId;
    }

    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public Contact getContact() {
        return contact;
    }

    public void setContact(Contact contact) {
        this.contact = contact;
    }
}

repozytorium Kontaktu:

Kopiuj

package domain;

import hibernate.utils.HibernateUtils;
import org.hibernate.Session;

import java.util.List;

public class ContactRepository {

    public static void listAllContacts(){

        Session session = null;
        try {
            session = HibernateUtils.openSession();
            List<Contact> listEmployee = session.createQuery("SELECT c FROM Contact c").getResultList();

            if (listEmployee == null) {
                System.out.println("No employee found . ");
            } else {
                for (Contact contact : listEmployee) {
                    System.out.println(contact.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }


    }

    public static void listContactById(Integer id){
        Session session = null;
        try {
            session = HibernateUtils.openSession();
            try{
                Contact contactById = session.find(Contact.class, id);
                System.out.println(contactById);
            } catch (NullPointerException e){
                System.out.println("No contact with id: " + id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    public static void addNewContact(Contact contact){

        Session session = null;
        try {
            session = HibernateUtils.openSession();
            session.getTransaction().begin();
            session.saveOrUpdate(contact);
            session.getTransaction().commit();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    public static void editExistingContact(Contact contactToUpdate){

        Session session = null;
        try {
            session = HibernateUtils.openSession();
            session.getTransaction().begin();
            session.merge(contactToUpdate);
            session.getTransaction().commit();
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            if (session != null && session.isOpen()) {
                session.close();
            }
        }

    }

    public static void deleteContact(int idToDelete){

        Session session = null;
        try {
            session = HibernateUtils.openSession();

            Contact contactToDelete = session.find(Contact.class, idToDelete);
            System.out.println(contactToDelete);

            session.getTransaction().begin();
            session.remove(contactToDelete);
            session.getTransaction().commit();

        }catch (Exception e){
            e.printStackTrace();
        }finally{
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }
}

repozytorium Grupy:

Kopiuj
package domain;

import hibernate.utils.HibernateUtils;
import org.hibernate.Session;

public class GroupRepository {

    public static void addNewGroup(Group group){

        Session session = null;
        try {
            session = HibernateUtils.openSession();
            session.getTransaction().begin();
            session.saveOrUpdate(group);
            session.getTransaction().commit();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }
}

Klasa zawierająca metodę main:

Kopiuj

import domain.Contact;
import domain.ContactRepository;
import domain.Group;
import domain.GroupRepository;
import hibernate.utils.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        boolean run = true;

        do {

            // MENU
            System.out.println("");
            System.out.println("MENU");
            System.out.println("=====================");
            System.out.println("1. List all contacts");
            System.out.println("2. Get contact by id");
            System.out.println("3. Add new contact");
            System.out.println("4. Update contact");
            System.out.println("5. Delete contact");
            System.out.println("6. Exit");
            System.out.println("=====================");
            System.out.println("");

            int choice = scanner.nextInt();

            switch (choice){

                case 1:
                    ContactRepository.listAllContacts();
                    break;
                case 2:
                    System.out.println("Type employee id:");
                    int id = scanner.nextInt();
                    ContactRepository.listContactById(id);
                    break;
                case 3:
                    System.out.println("Name: ");
                    String name = scanner.next();
                    System.out.println("Email: ");
                    String email = scanner.next();
                    System.out.println("Group: ");
                    String groupName = scanner.next();
                    Contact contact = new Contact(name, email);
                    Group group = new Group(groupName);
                    contact.setGroup(group);
                    ContactRepository.addNewContact(contact);
                    GroupRepository.addNewGroup(group);
                    break;

Błąd jaki dostaję przy próbie wypisania wszystkich danych z tabel (case 1):

Aug 05, 2018 6:49:04 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions WARN: SQL Error: 1, SQLState: null Aug 05, 2018 6:49:04 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions ERROR: [SQLITE_ERROR] SQL error or missing database (near "group": syntax error) javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423) at org.hibernate.query.Query.getResultList(Query.java:146) at domain.ContactRepository.listAllContacts(ContactRepository.java:15) at App.main(App.java:38) Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1985) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1915) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1893) at org.hibernate.loader.Loader.doQuery(Loader.java:938) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:311) at org.hibernate.loader.Loader.loadEntity(Loader.java:2282) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:61) at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:144) at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2228) at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:699) at org.hibernate.type.EntityType.resolve(EntityType.java:434) at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:165) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:125) at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1152) at org.hibernate.loader.Loader.processResultSet(Loader.java:1011) at org.hibernate.loader.Loader.doQuery(Loader.java:949) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) at org.hibernate.loader.Loader.doList(Loader.java:2692) at org.hibernate.loader.Loader.doList(Loader.java:2675) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2507) at org.hibernate.loader.Loader.list(Loader.java:2502) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:384) at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1490) at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1445) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414) ... 3 more Caused by: org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (near "group": syntax error) at org.sqlite.core.DB.newSQLException(DB.java:909) at org.sqlite.core.DB.newSQLException(DB.java:921) at org.sqlite.core.DB.throwex(DB.java:886) at org.sqlite.core.NativeDB.prepare_utf8(Native Method) at org.sqlite.core.NativeDB.prepare(NativeDB.java:127) at org.sqlite.core.DB.prepare(DB.java:227) at org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:41) at org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30) at org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:19) at org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:48) at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:263) at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:235) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172) ... 32 more

AK
sqllite jest szczególną bazą (tu i ówdzie nadmiernie tolerancyjną / o innej koncepcji typ/wartość), po drugie jest bezserwerowa, można zgadywać że wiele robi driverze JDBC / dialekcie hiberatowym. Mam przekonanie, że JPA + bazy głównego szeregu nie wylatują w powietrze na słowie 'group'. BTW dialekt masz dobrze ustawiony?
s-kaczmarek
Moim zdaniem dialekt jest ok, ponieważ zanim wprowadziłem relację wszystkie funkcje CRUD działały bezproblemowo.
YA
Nie znam sqllite, ale może spróbuj zmienić kolejność dodawania elementów do repo, tj. najpierw grupa a później kontakt. Obecnie dodajesz kontakt z ustawioną grupą, której to grupy w bazie jeszcze nie ma. Może to jest problemem dla sqllite.
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:8 minut
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
3

Możliwe, że błąd jest raczej zabawny. Group to słowo kluczowe SQL, więc nie może być nazwą tabeli.
Zmień na

Kopiuj
@Entity
@Table(name = "grub")
public class Group {

jeden i pół terabajta powinno wystarczyć każdemu
Haskell
  • Rejestracja:ponad 9 lat
  • Ostatnio:11 miesięcy
  • Postów:4700
1
jarekr000000 napisał(a):

Możliwe, że błąd jest raczej zabawny. Group to słowo kluczowe SQL, więc nie może być nazwą tabeli.

Oj tam zaraz nie może...

...po prostu nazwy będące słowami kluczowymi trzeba dać w square brackets ;)

Kopiuj
CREATE TABLE [GROUP]

Zaglądali do kufrów, zaglądali do waliz, nie zajrzeli do d**y - tam miałem socjalizm. Czesław Miłosz
s-kaczmarek
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:16
0

Niestety zmiana nazwy tabeli nic nie dała

Haskell
  • Rejestracja:ponad 9 lat
  • Ostatnio:11 miesięcy
  • Postów:4700
0

A jaki się teraz komunikat błedu wyświetla? Czytasz je chociaż?


Zaglądali do kufrów, zaglądali do waliz, nie zajrzeli do d**y - tam miałem socjalizm. Czesław Miłosz
s-kaczmarek
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:16
0

taki komunikat:

Aug 06, 2018 8:30:57 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.2.12.Final}
Aug 06, 2018 8:30:57 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Aug 06, 2018 8:30:57 PM org.hibernate.boot.jaxb.internal.stax.LocalXmlResourceResolver resolveEntity
WARN: HHH90000012: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/hibernate-configuration. Use namespace http://www.hibernate.org/dtd/hibernate-configuration instead. Support for obsolete DTD/XSD namespaces may be removed at any time.
Aug 06, 2018 8:30:57 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.sqlite.JDBC] at URL [jdbc:sqlite:mydb.db]
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=, password=****}
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Aug 06, 2018 8:30:57 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.SQLiteDialect
Aug 06, 2018 8:30:57 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [2] less than 4
Initial SessionFactory creation failed.org.hibernate.AnnotationException: Unknown mappedBy in: domain.Group.contact, referenced property unknown: domain.Contact.contact
Exception in thread "main" java.lang.ExceptionInInitializerError: Connection to database error!
at hibernate.utils.HibernateUtils.<clinit>(HibernateUtils.java:16)
at domain.ContactRepository.listAllContacts(ContactRepository.java:14)
at App.main(App.java:35)

Czytam, aczkolwiek niewiele mi one mówią. Końcówka mi się rzuciła w oczy:

Initial SessionFactory creation failed.org.hibernate.AnnotationException: Unknown mappedBy in: domain.Group.contact, referenced property unknown: domain.Contact.contact
Exception in thread "main" java.lang.ExceptionInInitializerError: Connection to database error!
at hibernate.utils.HibernateUtils.<clinit>(HibernateUtils.java:16)
at domain.ContactRepository.listAllContacts(ContactRepository.java:14)
at App.main(App.java:35)

Mimo wszystko nie wiem co ona oznacza, dodam, że taki komunikat pojawił się w momencie wyboru pierwszego case'a, czyli wypisania wszystkich danych.

discoStar
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Wlk. Brytania
  • Postów:92
0

Może spróbuj:

Kopiuj
@OneToOne(mappedBy = "id", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Group group;

https://www.google.co.uk/search?q=Unknown+mappedBy+referenced+property+unknown&oq=Unknown+mappedBy+referenced+property+unknown&aqs=chrome..69i57j0l5.3736j0j7&sourceid=chrome&ie=UTF-8

Swoją drogą @jarekr000000 zamiast switch'a można by było użyć strategii? Dobrze myślę?

edytowany 1x, ostatnio: discoStar
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:8 minut
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1
discoStar napisał(a):

Może spróbuj:

Kopiuj
@OneToOne(mappedBy = "id", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Group group;

Swoją drogą @jarekr000000 zamiast switch'a można by było użyć strategii? Dobrze myślę?

Ten mappedBy = "id" to raczej zły pomysł. Po prostu lepiej wywalić @MapsId (ciekawe skąd w ogóle OP to wytrzasnął?).
A co do strategii to można, ale nie wolno. Niech się lepiej początkujący skupi na nauce programowania, a nie na wzorcach.


jeden i pół terabajta powinno wystarczyć każdemu
jarekczek
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Siemianowice Śląskie
  • Postów:500
0

Zauważ, @s-kaczmarek, że teraz musimy zgadywać - co jest nie tak. Alternatywą jest podejrzeć uruchamiane polecenia sql. Najcześciej wtedy od razu widać, gdzie jest pies pogrzebany. Są na to 2 sposoby:

  1. Włączyć poziom logowania DEBUG na klasie org.hibernate.SQL (dokładnie nie pamiętam). Na początek można włączyć go globalnie (albo na org.hibernate), a potem okroić, jak już będzie wiadomo, co nas interesuje.
  2. Jest przełącznik JPA/Hibernate property, który powoduje wyświetlanie rozkazów SQL.

A jak mam zgadywać, to wyrzucam @MapsId i ustawiam nazwy kolumn wielkimi literami (@ColumnName). Czytam poza tym Vlada Michalceę.

Edit: Ciągle masz słowo kluczowe Group (jako nazwa kolumny).


Przeważnie ignoruję niezarejestrowanych użytkowników.
edytowany 2x, ostatnio: jarekczek
s-kaczmarek
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:16
0

Problem rozwiązany:

Faktycznie nazwa tabeli nie może być "group", ale to nie był jedyny problem. Z encji Group wywaliłem pole "contact", a w encji Contact nad polem "group" dodałem tylko adnotację @OneToOne bez dodatkowych parametrów. Na koniec od komentowałem zapis obiektu encji Group do bazy. Błędnie sądziłem, że przy relacji jeden-do-jednego musimy w obu encjach utworzyć pola przechowujące obiekty encji do których ma być relacja. Czegoś nowego się nauczyłem. Dzięki za pomoc!

MO
unidirectional one-to-one vs bidirectional one-to-one. zależy co potrzeba
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)