Justin.Bell
Justin.Bell

Reputation: 105

Mapping objects with a mapping entity

I'm trying to figure out what I'm doing wrong with this, but I'm learning hibernate annotations and creating a simple library system. Basically, a book gets checked out by a person, and eventually checked in. Here's how I have it configured:

@Entity
@Table
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false, unique = true)
    private long barcode;
    @Column(nullable = false)
    private String name;
    @OneToMany
    @JoinTable(name = "checkoutsession", joinColumns = { @JoinColumn(name = "book") }, inverseJoinColumns = { @JoinColumn(name = "id")})
    private List<CheckOutSession> checkOutSessions;
}

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(nullable = false, unique = true)
    private long barcode;
    @Column(name = "firstname")
    private String firstName;
    @Column(name = "lastname")
    private String lastName;
    @OneToMany
    @JoinTable(name = "checkoutsession", joinColumns = { @JoinColumn(name = "user") }, inverseJoinColumns = { @JoinColumn(name = "id")})
    private List<CheckOutSession> checkOutSessions;
}

@Entity
@Table(name = "checkoutsession", uniqueConstraints = {@UniqueConstraint(columnNames={"book", "checkIn"})})
public class CheckOutSession {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @ManyToOne
    @JoinColumn(name="book", nullable=false)
    private Book book;
    @ManyToOne
    @JoinColumn(name="user", nullable=false)
    private User user;
    @Column(nullable = false)
    private java.sql.Timestamp checkOut;
    @Column
    private java.sql.Timestamp checkIn;
}

I can't figure out for the life of me what I've got configured incorrectly.

[EDIT]

when I try to pull a book it is selecting everything from checkoutsession join checkoutsession join user and dies saying "Unknown column checkoutsess1_.check_in in 'field list';

[EDIT2]

A little more context, I have a BookDAO that extends JpaRepository and when I call findAll() is what's creating that query.

[EDIT3]

Rest Class:

@RestController
@RequestMapping("rest/books")
public class BookController {

@RequestMapping(method = RequestMethod.GET)
    public List findBooks() {
        return bookService.getAllBooks();
    }

}

Service:

@Component
public class BookService {

    private BookDao bookDao;

    public List getAllBooks() {
        return bookDao.findAll();
    }

    @Autowired
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

}

DAO:

public interface BookDao extends JpaRepository<Book, Long> {

}

Thanks for any help!

Upvotes: 0

Views: 116

Answers (1)

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44745

If I run your code and make JPA generate tables based on the entities it seems to work (at least, it does run).

However, your mappings appear to be odd to me, more specifically the @JoinTable annotation. The @JoinTable annotation is commonly used when you have a join table (eg. checkoutSession in your case), but you don't want to map it because it contains no useful information except the links between those two tables.

In that case, you use the @JoinTable annotation as following:

@ManyToMany
@JoinTable(
    name = "checkoutsession", // Name of the join table
    joinColumns = @JoinColumn(name = "book"), // The column name in checkoutsession that links to book
    inverseJoinColumns = @JoinColumn(name = "user") // The column name in checkoutsession that links to user
)
private List<User> users;

So in this case, you can directly link the Book and User entity without having to create the CheckoutSession entity.

However, in your case your join table also contains two timestamps, if you need those in your application, then you don't have to use @JoinTable but simply use @JoinColumn to link them, for example:

@OneToMany(mappedBy = "book") // The field name in CheckoutSession that links to book
private List<CheckoutSession> checkOutSessions;

This is what you should have in your Book entity. Be aware that in this case we're talking about field names not about column names. You have to enter the name of the field in CheckoutSession that maps back to the Book entity.

For more information about the @JoinTable annotation I recommend you to read this answer: JPA "@JoinTable" annotation or this article.

Upvotes: 1

Related Questions