0

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!

4
  • are you getting any exception? Commented Jan 14, 2016 at 0:16
  • sorry, just edited to add the issue I'm getting. Commented Jan 14, 2016 at 0:16
  • Please show a snippet of the calling code. Commented Jan 14, 2016 at 0:21
  • I just added the calling code. Commented Jan 14, 2016 at 0:25

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

That was it, thanks so much! I had read through the documentation and misunderstood what the @JoinTable annotation was for. I replaced it with the mappedBy and everything is working as expected now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.